From 93b939835f025cfd178d88f77bd1fe5cefb292b7 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sun, 7 Jun 2020 10:14:46 -0400 Subject: [PATCH 01/24] Initial definition of modifiers and how they will be shown in preferences --- src/modifiers.cpp | 82 ++++++++++++ src/modifiers.h | 174 +++++++++++++++++++++++++ src/ui/dialog/inkscape-preferences.cpp | 22 ++++ 3 files changed, 278 insertions(+) create mode 100644 src/modifiers.cpp create mode 100644 src/modifiers.h diff --git a/src/modifiers.cpp b/src/modifiers.cpp new file mode 100644 index 0000000000..2b14e071d8 --- /dev/null +++ b/src/modifiers.cpp @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * Modifiers for inkscape + * + * The file provides a definition of all the ways shift/ctrl/alt modifiers + * are used in Inkscape, and allows users to customise them in keys.xml + * + *//* + * Authors: + * 2020 Martin Owens + * + * Copyright (C) 2018 Authors + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include +#include +#include "modifiers.h" + +namespace Inkscape { + +Modifier::ModifierLookup Modifier::_modifier_lookup; + +// these must be in the same order as the SP_MODIFIER_* enum in "modifers.h" +Modifier *Modifier::_modifiers[] = { + // Header + new Modifier(SP_MODIFIER_INVALID, nullptr, nullptr, nullptr, 0), + + // Canvas modifiers + new Modifier(SP_MODIFIER_CANVAS_SCROLL_Y, "canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0), + new Modifier(SP_MODIFIER_CANVAS_SCROLL_X, "canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT), + new Modifier(SP_MODIFIER_CANVAS_ZOOM, "canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL), + new Modifier(SP_MODIFIER_CANVAS_ROTATE, "canvas-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL), + + // Select tool modifiers (minus transforms) + new Modifier(SP_MODIFIER_SELECT_ADD_TO, "select-add-to", "Add to selection", "Add items to existing selection", SHIFT), + new Modifier(SP_MODIFIER_SELECT_IN_GROUPS, "select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL), + new Modifier(SP_MODIFIER_SELECT_TOUCH_PATH, "select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT), + new Modifier(SP_MODIFIER_SELECT_ALWAYS_BOX, "select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT), + new Modifier(SP_MODIFIER_SELECT_FIRST_HIT, "select-first-hit", "Select the first", "Scroll up and down", CTRL), + + // Transform handle modifiers (applies to multiple tools) + new Modifier(SP_MODIFIER_MOVE_AXIS_CONFINE, "move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL), + new Modifier(SP_MODIFIER_SCALE_RATIO_CONFINE, "scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL), + new Modifier(SP_MODIFIER_SCALE_FROM_CENTER, "scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT), + new Modifier(SP_MODIFIER_SCALE_FIXED_RATIO, "scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT), + new Modifier(SP_MODIFIER_TRANS_FIXED_RATIO, "trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL), + new Modifier(SP_MODIFIER_TRANS_OFF_CENTER, "trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT), + + // Footer + new Modifier(SP_MODIFIER_LAST, " '\"invalid id", nullptr, nullptr, 0) +}; + +std::vector +Modifier::getList () { + + std::vector modifiers; + // Go through the dynamic modifier table + for (auto & _modifier : _modifiers) { + Modifier * modifier = _modifier; + if (modifier->get_index() == SP_MODIFIER_INVALID || + modifier->get_index() == SP_MODIFIER_LAST) { + continue; + } + modifiers.push_back(modifier); + } + + return modifiers; +}; + +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/modifiers.h b/src/modifiers.h new file mode 100644 index 0000000000..03c3d86bbf --- /dev/null +++ b/src/modifiers.h @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#ifndef SEEN_SP_MODIFIERS_H +#define SEEN_SP_MODIFIERS_H +/* + * Copyright (C) 2020 Martin Owens + + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include +#include +#include +#include +//#include + +int SHIFT = 1; // GDK_SHIFT_MASK; +int CTRL = 4; // GDK_CONTROL_MASK; +int ALT = 8; // GDK_MOD1_MASK; + +/** + * This anonymous enum is used to provide a list of the Shifts + */ +enum { + SP_MODIFIER_INVALID, + // SP_MODIFIER_{TOOL_NAME}_{ACTION_NAME} + + // Canvas tools (applies to any tool selection) + SP_MODIFIER_CANVAS_SCROLL_Y, // Scroll up and down {NOTHING+SCROLL} + SP_MODIFIER_CANVAS_SCROLL_X, // Scroll left and right {SHIFT+SCROLL} + SP_MODIFIER_CANVAS_ZOOM, // Zoom in and out {CTRL+SCROLL} + SP_MODIFIER_CANVAS_ROTATE, // Rotate CW and CCW {CTRL+SHIFT+SCROLL} + + // Select tool (minus transform) + SP_MODIFIER_SELECT_ADD_TO, // Add selection {SHIFT+CLICK} + SP_MODIFIER_SELECT_IN_GROUPS, // Select within groups {CTRL+CLICK} + SP_MODIFIER_SELECT_TOUCH_PATH, // Draw band to select {ALT+DRAG} + SP_MODIFIER_SELECT_ALWAYS_BOX, // Draw box to select {SHIFT+DRAG} + SP_MODIFIER_SELECT_FIRST_HIT, // Start dragging first item hit {CTRL+DRAG} (Is this an actual feature?) + + // Transform handles (applies to multiple tools) + SP_MODIFIER_MOVE_AXIS_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} + SP_MODIFIER_SCALE_RATIO_CONFINE, // Confine resize aspect ratio {HANDLE+CTRL} + SP_MODIFIER_SCALE_FROM_CENTER, // Resize from center {HANDLE+SHIFT} + SP_MODIFIER_SCALE_FIXED_RATIO, // Resize by fixed ratio sizes {HANDLE+ALT} + SP_MODIFIER_TRANS_FIXED_RATIO, // Rotate/skew by fixed ratio angles {HANDLE+CTRL} + SP_MODIFIER_TRANS_OFF_CENTER, // Rotate/skew from oposite corner {HANDLE+SHIFT} + // TODO: Alignment ommitted because it's UX is not completed + + /* Footer */ + SP_MODIFIER_LAST +}; + +namespace Inkscape { + +/** + * A class to represent ways functionality is driven by shift modifiers + */ +class Modifier { +private: + /** An easy to use definition of the table of modifiers by ID. */ + typedef std::map ModifierLookup; + + /** A table of all the created modifers. */ + static ModifierLookup _modifier_lookup; + + static Modifier * _modifiers[SP_MODIFIER_LAST + 1]; + /* Plus one because there is an entry for SP_MODIFIER_LAST */ + + // Fixed data defined in code and created at run time + + unsigned int _index; // Index of the modifier, based on the modifier enum + char const * _id; // A unique id used by keys.xml to identify it + char const * _name; // A descriptive name used in preferences UI + char const * _desc; // A more verbose description used in preferences UI + //char const * _group; // Optional group for preferences UI + unsigned int _default; // The default value if nothing set in keys.xml + + // User set data + signed int _value; // The value set by keys.xml, set to -1 if unset. + +protected: + +public: + + unsigned int get_index () { return _index; } + char const * get_id () { return _id; } + char const * get_name () { return _name; } + char const * get_description () { return _desc; } + //char const * get_group () { return _group; } + + // Set user value + bool is_user_set() { return _value != -1; } + void set_value (unsigned int value) { _value = value; } + void unset_value() { _value = -1; } + + // Get value, either user defined value or default + unsigned int get_value() { + if(is_user_set()) { + return _value; + } + return _default; + } + + /** + * Inititalizes the Modifier with the parameters. + * + * @param index Goes to \c _index. + * @param id Goes to \c _id. + * @param name Goes to \c _name. + * @param desc Goes to \c _desc. + * @param default_ Goes to \c _default. + */ + Modifier(const unsigned int index, + char const * id, + char const * name, + char const * desc, + const unsigned int default_) : + _index(index), + _id(id), + _name(name), + _desc(desc), + _default(default_), + _value(-1) + { + _modifier_lookup.insert(ModifierLookup::value_type(_id, this)); + } + static void list (); + static std::vectorgetList (); + + /** + * A function to turn an enum index into a modifier object. + * + * @param index The enum index to be translated + * @return A pointer to a modifier object or a NULL if not found. + */ + static Modifier * get(unsigned int index) { + if (index <= SP_MODIFIER_LAST) { + return _modifiers[index]; + } + } + /** + * A function to turn a string id into a modifier object. + * + * @param id The id string to be translated + * @return A pointer to a modifier object or a NULL if not found. + */ + static Modifier * get(char const * id) { + Modifier *modifier = nullptr; + ModifierLookup::iterator mod_found = _modifier_lookup.find(id); + + if (mod_found != _modifier_lookup.end()) { + modifier = mod_found->second; + } + + return modifier; + } + +}; /* Modifier class */ + + +} /* Inkscape namespace */ + +#endif // SEEN_SP_MODIFIERS_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 5382671a4c..27cbe8eab9 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -2552,6 +2552,28 @@ void InkscapePreferences::onKBListKeyboardShortcuts() } } + // Tool mouse keys + Gtk::TreeStore::iterator iter_modifers = _kb_store->append(); + (*iter_modifers)[_kb_columns.name] = _("Modifiers"); + (*iter_modifers)[_kb_columns.shortcut] = ""; + (*iter_modifers)[_kb_columns.id] = ""; + (*iter_modifers)[_kb_columns.description] = ""; + (*iter_modifers)[_kb_columns.shortcutid] = 0; + (*iter_modifers)[_kb_columns.user_set] = 0; + + for(auto modifier: Modifier::getList()) { + + // TODO: generate shortcut label and shortcut id etc + Gtk::TreeStore::iterator iter_modifer = _kb_store->append(); + (*iter_modifer)[_kb_columns.name] = modifier->get_name(); + (*iter_modifer)[_kb_columns.shortcut] = ""; + (*iter_modifer)[_kb_columns.id] = modifier->get_id(); + (*iter_modifer)[_kb_columns.description] = modifier->get_description(); + (*iter_modifer)[_kb_columns.shortcutid] = 0; + (*iter_modifer)[_kb_columns.user_set] = modifier->is_user_set(); + + } + // re-order once after updating (then disable ordering again to increase performance) _kb_store->set_sort_column (_kb_columns.id, Gtk::SORT_ASCENDING ); _kb_store->set_sort_column ( GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, Gtk::SORT_ASCENDING ); -- GitLab From 13c2e1b6f5af3d9feb603f85c2ac9dc75a4bb80c Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Mon, 8 Jun 2020 10:26:32 -0400 Subject: [PATCH 02/24] Move modifiers to ui and clean up the structure some more --- src/modifiers.cpp | 82 -------------------------- src/ui/CMakeLists.txt | 2 + src/ui/dialog/inkscape-preferences.cpp | 4 +- src/ui/modifiers.cpp | 73 +++++++++++++++++++++++ src/{ => ui}/modifiers.h | 78 ++++++++++++------------ 5 files changed, 116 insertions(+), 123 deletions(-) delete mode 100644 src/modifiers.cpp create mode 100644 src/ui/modifiers.cpp rename src/{ => ui}/modifiers.h (61%) diff --git a/src/modifiers.cpp b/src/modifiers.cpp deleted file mode 100644 index 2b14e071d8..0000000000 --- a/src/modifiers.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/** @file - * Modifiers for inkscape - * - * The file provides a definition of all the ways shift/ctrl/alt modifiers - * are used in Inkscape, and allows users to customise them in keys.xml - * - *//* - * Authors: - * 2020 Martin Owens - * - * Copyright (C) 2018 Authors - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#include -#include -#include "modifiers.h" - -namespace Inkscape { - -Modifier::ModifierLookup Modifier::_modifier_lookup; - -// these must be in the same order as the SP_MODIFIER_* enum in "modifers.h" -Modifier *Modifier::_modifiers[] = { - // Header - new Modifier(SP_MODIFIER_INVALID, nullptr, nullptr, nullptr, 0), - - // Canvas modifiers - new Modifier(SP_MODIFIER_CANVAS_SCROLL_Y, "canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0), - new Modifier(SP_MODIFIER_CANVAS_SCROLL_X, "canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT), - new Modifier(SP_MODIFIER_CANVAS_ZOOM, "canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL), - new Modifier(SP_MODIFIER_CANVAS_ROTATE, "canvas-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL), - - // Select tool modifiers (minus transforms) - new Modifier(SP_MODIFIER_SELECT_ADD_TO, "select-add-to", "Add to selection", "Add items to existing selection", SHIFT), - new Modifier(SP_MODIFIER_SELECT_IN_GROUPS, "select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL), - new Modifier(SP_MODIFIER_SELECT_TOUCH_PATH, "select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT), - new Modifier(SP_MODIFIER_SELECT_ALWAYS_BOX, "select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT), - new Modifier(SP_MODIFIER_SELECT_FIRST_HIT, "select-first-hit", "Select the first", "Scroll up and down", CTRL), - - // Transform handle modifiers (applies to multiple tools) - new Modifier(SP_MODIFIER_MOVE_AXIS_CONFINE, "move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL), - new Modifier(SP_MODIFIER_SCALE_RATIO_CONFINE, "scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL), - new Modifier(SP_MODIFIER_SCALE_FROM_CENTER, "scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT), - new Modifier(SP_MODIFIER_SCALE_FIXED_RATIO, "scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT), - new Modifier(SP_MODIFIER_TRANS_FIXED_RATIO, "trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL), - new Modifier(SP_MODIFIER_TRANS_OFF_CENTER, "trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT), - - // Footer - new Modifier(SP_MODIFIER_LAST, " '\"invalid id", nullptr, nullptr, 0) -}; - -std::vector -Modifier::getList () { - - std::vector modifiers; - // Go through the dynamic modifier table - for (auto & _modifier : _modifiers) { - Modifier * modifier = _modifier; - if (modifier->get_index() == SP_MODIFIER_INVALID || - modifier->get_index() == SP_MODIFIER_LAST) { - continue; - } - modifiers.push_back(modifier); - } - - return modifiers; -}; - -} // namespace Inkscape - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 71217fa463..d976381d3a 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -18,6 +18,7 @@ set(ui_SRC tools-switch.cpp util.cpp uxmanager.cpp + modifiers.cpp cache/svg_preview_cache.cpp @@ -250,6 +251,7 @@ set(ui_SRC tools-switch.h util.h uxmanager.h + modifiers.h cache/svg_preview_cache.h diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 27cbe8eab9..76bcc68214 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -2561,7 +2561,7 @@ void InkscapePreferences::onKBListKeyboardShortcuts() (*iter_modifers)[_kb_columns.shortcutid] = 0; (*iter_modifers)[_kb_columns.user_set] = 0; - for(auto modifier: Modifier::getList()) { + /*for(auto modifier: Modifier::getList()) { // TODO: generate shortcut label and shortcut id etc Gtk::TreeStore::iterator iter_modifer = _kb_store->append(); @@ -2572,7 +2572,7 @@ void InkscapePreferences::onKBListKeyboardShortcuts() (*iter_modifer)[_kb_columns.shortcutid] = 0; (*iter_modifer)[_kb_columns.user_set] = modifier->is_user_set(); - } + }*/ // re-order once after updating (then disable ordering again to increase performance) _kb_store->set_sort_column (_kb_columns.id, Gtk::SORT_ASCENDING ); diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp new file mode 100644 index 0000000000..86d1a3b1fc --- /dev/null +++ b/src/ui/modifiers.cpp @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * Modifiers for inkscape + * + * The file provides a definition of all the ways shift/ctrl/alt modifiers + * are used in Inkscape, and allows users to customise them in keys.xml + * + *//* + * Authors: + * 2020 Martin Owens + * + * Copyright (C) 2018 Authors + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include +#include +#include "modifiers.h" + +namespace Inkscape { +namespace Modifier { + +Modifier::Lookup Modifier::_modifier_lookup; + +// these must be in the same order as the * enum in "modifers.h" +Modifier *Modifier::_modifiers[] = { + // Canvas modifiers + new Modifier(CANVAS_SCROLL_Y, "canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0), + new Modifier(CANVAS_SCROLL_X, "canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT), + new Modifier(CANVAS_ZOOM, "canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL), + new Modifier(CANVAS_ROTATE, "canvas-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL), + + // Select tool modifiers (minus transforms) + new Modifier(SELECT_ADD_TO, "select-add-to", "Add to selection", "Add items to existing selection", SHIFT), + new Modifier(SELECT_IN_GROUPS, "select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL), + new Modifier(SELECT_TOUCH_PATH, "select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT), + new Modifier(SELECT_ALWAYS_BOX, "select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT), + new Modifier(SELECT_FIRST_HIT, "select-first-hit", "Select the first", "Scroll up and down", CTRL), + + // Transform handle modifiers (applies to multiple tools) + new Modifier(MOVE_AXIS_CONFINE, "move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL), + new Modifier(SCALE_RATIO_CONFINE, "scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL), + new Modifier(SCALE_FROM_CENTER, "scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT), + new Modifier(SCALE_FIXED_RATIO, "scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT), + new Modifier(TRANS_FIXED_RATIO, "trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL), + new Modifier(TRANS_OFF_CENTER, "trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT), +}; + +std::vector +Modifier::getList () { + + std::vector modifiers; + // Go through the dynamic modifier table + for (Modifier * modifier : _modifiers) { + modifiers.push_back(modifier); + } + + return modifiers; +}; + +} // namespace Modifier +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/modifiers.h b/src/ui/modifiers.h similarity index 61% rename from src/modifiers.h rename to src/ui/modifiers.h index 03c3d86bbf..a5ecba34f1 100644 --- a/src/modifiers.h +++ b/src/ui/modifiers.h @@ -13,44 +13,46 @@ #include //#include +namespace Inkscape { +namespace Modifier { + int SHIFT = 1; // GDK_SHIFT_MASK; int CTRL = 4; // GDK_CONTROL_MASK; int ALT = 8; // GDK_MOD1_MASK; +int NON_USER = -1; /** * This anonymous enum is used to provide a list of the Shifts */ -enum { - SP_MODIFIER_INVALID, - // SP_MODIFIER_{TOOL_NAME}_{ACTION_NAME} +enum Type { + // {TOOL_NAME}_{ACTION_NAME} // Canvas tools (applies to any tool selection) - SP_MODIFIER_CANVAS_SCROLL_Y, // Scroll up and down {NOTHING+SCROLL} - SP_MODIFIER_CANVAS_SCROLL_X, // Scroll left and right {SHIFT+SCROLL} - SP_MODIFIER_CANVAS_ZOOM, // Zoom in and out {CTRL+SCROLL} - SP_MODIFIER_CANVAS_ROTATE, // Rotate CW and CCW {CTRL+SHIFT+SCROLL} + CANVAS_SCROLL_Y, // Scroll up and down {NOTHING+SCROLL} + CANVAS_SCROLL_X, // Scroll left and right {SHIFT+SCROLL} + CANVAS_ZOOM, // Zoom in and out {CTRL+SCROLL} + CANVAS_ROTATE, // Rotate CW and CCW {CTRL+SHIFT+SCROLL} // Select tool (minus transform) - SP_MODIFIER_SELECT_ADD_TO, // Add selection {SHIFT+CLICK} - SP_MODIFIER_SELECT_IN_GROUPS, // Select within groups {CTRL+CLICK} - SP_MODIFIER_SELECT_TOUCH_PATH, // Draw band to select {ALT+DRAG} - SP_MODIFIER_SELECT_ALWAYS_BOX, // Draw box to select {SHIFT+DRAG} - SP_MODIFIER_SELECT_FIRST_HIT, // Start dragging first item hit {CTRL+DRAG} (Is this an actual feature?) + SELECT_ADD_TO, // Add selection {SHIFT+CLICK} + SELECT_IN_GROUPS, // Select within groups {CTRL+CLICK} + SELECT_TOUCH_PATH, // Draw band to select {ALT+DRAG} + SELECT_ALWAYS_BOX, // Draw box to select {SHIFT+DRAG} + SELECT_FIRST_HIT, // Start dragging first item hit {CTRL+DRAG} (Is this an actual feature?) // Transform handles (applies to multiple tools) - SP_MODIFIER_MOVE_AXIS_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} - SP_MODIFIER_SCALE_RATIO_CONFINE, // Confine resize aspect ratio {HANDLE+CTRL} - SP_MODIFIER_SCALE_FROM_CENTER, // Resize from center {HANDLE+SHIFT} - SP_MODIFIER_SCALE_FIXED_RATIO, // Resize by fixed ratio sizes {HANDLE+ALT} - SP_MODIFIER_TRANS_FIXED_RATIO, // Rotate/skew by fixed ratio angles {HANDLE+CTRL} - SP_MODIFIER_TRANS_OFF_CENTER, // Rotate/skew from oposite corner {HANDLE+SHIFT} + MOVE_AXIS_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} + SCALE_RATIO_CONFINE, // Confine resize aspect ratio {HANDLE+CTRL} + SCALE_FROM_CENTER, // Resize from center {HANDLE+SHIFT} + SCALE_FIXED_RATIO, // Resize by fixed ratio sizes {HANDLE+ALT} + TRANS_FIXED_RATIO, // Rotate/skew by fixed ratio angles {HANDLE+CTRL} + TRANS_OFF_CENTER, // Rotate/skew from oposite corner {HANDLE+SHIFT} // TODO: Alignment ommitted because it's UX is not completed /* Footer */ - SP_MODIFIER_LAST + LAST }; -namespace Inkscape { /** * A class to represent ways functionality is driven by shift modifiers @@ -58,17 +60,17 @@ namespace Inkscape { class Modifier { private: /** An easy to use definition of the table of modifiers by ID. */ - typedef std::map ModifierLookup; + typedef std::map Lookup; /** A table of all the created modifers. */ - static ModifierLookup _modifier_lookup; + static Lookup _modifier_lookup; - static Modifier * _modifiers[SP_MODIFIER_LAST + 1]; - /* Plus one because there is an entry for SP_MODIFIER_LAST */ + static Modifier * _modifiers[LAST + 1]; + /* Plus one because there is an entry for LAST */ // Fixed data defined in code and created at run time - unsigned int _index; // Index of the modifier, based on the modifier enum + Type _index; // Index of the modifier, based on the modifier enum char const * _id; // A unique id used by keys.xml to identify it char const * _name; // A descriptive name used in preferences UI char const * _desc; // A more verbose description used in preferences UI @@ -82,16 +84,16 @@ protected: public: - unsigned int get_index () { return _index; } + Type get_index () { return _index; } char const * get_id () { return _id; } char const * get_name () { return _name; } char const * get_description () { return _desc; } //char const * get_group () { return _group; } // Set user value - bool is_user_set() { return _value != -1; } + bool is_user_set() { return _value != NON_USER; } void set_value (unsigned int value) { _value = value; } - void unset_value() { _value = -1; } + void unset_value() { _value = NON_USER; } // Get value, either user defined value or default unsigned int get_value() { @@ -110,7 +112,7 @@ public: * @param desc Goes to \c _desc. * @param default_ Goes to \c _default. */ - Modifier(const unsigned int index, + Modifier(Type index, char const * id, char const * name, char const * desc, @@ -122,10 +124,10 @@ public: _default(default_), _value(-1) { - _modifier_lookup.insert(ModifierLookup::value_type(_id, this)); + _modifier_lookup.emplace(_id, this); } static void list (); - static std::vectorgetList (); + static std::vectorgetList (); /** * A function to turn an enum index into a modifier object. @@ -133,10 +135,8 @@ public: * @param index The enum index to be translated * @return A pointer to a modifier object or a NULL if not found. */ - static Modifier * get(unsigned int index) { - if (index <= SP_MODIFIER_LAST) { - return _modifiers[index]; - } + static Modifier * get(Type index) { + return _modifiers[index]; } /** * A function to turn a string id into a modifier object. @@ -146,7 +146,7 @@ public: */ static Modifier * get(char const * id) { Modifier *modifier = nullptr; - ModifierLookup::iterator mod_found = _modifier_lookup.find(id); + Lookup::iterator mod_found = _modifier_lookup.find(id); if (mod_found != _modifier_lookup.end()) { modifier = mod_found->second; @@ -155,10 +155,10 @@ public: return modifier; } -}; /* Modifier class */ - +}; // Modifier class -} /* Inkscape namespace */ +} // Modifier namespace +} // Inkscape namespace #endif // SEEN_SP_MODIFIERS_H -- GitLab From 0a42ad1f2ab3253bf7c5f28755b47b32160f529b Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Mon, 8 Jun 2020 11:17:43 -0400 Subject: [PATCH 03/24] Use type names to be concise with variables. --- src/ui/modifiers.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index a5ecba34f1..8a8c71dd66 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -16,10 +16,12 @@ namespace Inkscape { namespace Modifier { -int SHIFT = 1; // GDK_SHIFT_MASK; -int CTRL = 4; // GDK_CONTROL_MASK; -int ALT = 8; // GDK_MOD1_MASK; -int NON_USER = -1; +using KeyMask = int; + +KeyMask NON_USER = -1; +KeyMask SHIFT = 1; // GDK_SHIFT_MASK; +KeyMask CTRL = 4; // GDK_CONTROL_MASK; +KeyMask ALT = 8; // GDK_MOD1_MASK; /** * This anonymous enum is used to provide a list of the Shifts @@ -75,16 +77,16 @@ private: char const * _name; // A descriptive name used in preferences UI char const * _desc; // A more verbose description used in preferences UI //char const * _group; // Optional group for preferences UI - unsigned int _default; // The default value if nothing set in keys.xml + KeyMask _default; // The default value if nothing set in keys.xml // User set data - signed int _value; // The value set by keys.xml, set to -1 if unset. + KeyMask _value; // The value set by keys.xml, set to -1 if unset. protected: public: - Type get_index () { return _index; } + const Type get_index () { return _index; } char const * get_id () { return _id; } char const * get_name () { return _name; } char const * get_description () { return _desc; } @@ -92,11 +94,11 @@ public: // Set user value bool is_user_set() { return _value != NON_USER; } - void set_value (unsigned int value) { _value = value; } + void set_value (KeyMask value) { _value = value; } void unset_value() { _value = NON_USER; } // Get value, either user defined value or default - unsigned int get_value() { + const KeyMask get_value() { if(is_user_set()) { return _value; } @@ -116,7 +118,7 @@ public: char const * id, char const * name, char const * desc, - const unsigned int default_) : + const KeyMask default_) : _index(index), _id(id), _name(name), -- GitLab From 6f2e6b8861bb4c532f15c543078bfdde4d8aa7f4 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Mon, 8 Jun 2020 11:21:14 -0400 Subject: [PATCH 04/24] Set default value in code, rather than constructor --- src/ui/modifiers.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 8a8c71dd66..1f54ed7c33 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -80,7 +80,7 @@ private: KeyMask _default; // The default value if nothing set in keys.xml // User set data - KeyMask _value; // The value set by keys.xml, set to -1 if unset. + KeyMask _value = NON_USER; // The value set by keys.xml protected: @@ -123,8 +123,7 @@ public: _id(id), _name(name), _desc(desc), - _default(default_), - _value(-1) + _default(default_) { _modifier_lookup.emplace(_id, this); } -- GitLab From d0afb432ab19a73def0db9e76d064f23fb8af9ce Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Mon, 8 Jun 2020 11:27:05 -0400 Subject: [PATCH 05/24] Make Modifier type eternal (undestroyable) --- src/ui/modifiers.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 1f54ed7c33..46c0035c9d 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -86,14 +86,14 @@ protected: public: - const Type get_index () { return _index; } - char const * get_id () { return _id; } - char const * get_name () { return _name; } - char const * get_description () { return _desc; } - //char const * get_group () { return _group; } + const Type get_index() const { return _index; } + char const * get_id() const { return _id; } + char const * get_name() const { return _name; } + char const * get_description() const { return _desc; } + //char const * get_group() const { return _group; } // Set user value - bool is_user_set() { return _value != NON_USER; } + bool is_user_set() const { return _value != NON_USER; } void set_value (KeyMask value) { _value = value; } void unset_value() { _value = NON_USER; } @@ -127,6 +127,9 @@ public: { _modifier_lookup.emplace(_id, this); } + // Delete the destructor, because we are eternal + ~Modifier() = delete; + static void list (); static std::vectorgetList (); -- GitLab From 0e21599c6c385ba3bd63ac8167091648397f19be Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Wed, 10 Jun 2020 18:40:32 -0400 Subject: [PATCH 06/24] First use of active function and cleanups --- src/ui/modifiers.cpp | 25 +++++++++++++++--- src/ui/modifiers.h | 51 ++++++++++++++++++++---------------- src/ui/tools/select-tool.cpp | 21 +++++++++++---- 3 files changed, 66 insertions(+), 31 deletions(-) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 86d1a3b1fc..fd273ed4ce 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -18,9 +18,7 @@ #include "modifiers.h" namespace Inkscape { -namespace Modifier { - -Modifier::Lookup Modifier::_modifier_lookup; +namespace Modifiers { // these must be in the same order as the * enum in "modifers.h" Modifier *Modifier::_modifiers[] = { @@ -46,6 +44,11 @@ Modifier *Modifier::_modifiers[] = { new Modifier(TRANS_OFF_CENTER, "trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT), }; +/** + * List all the modifiers available. Used in UI listing. + * + * @return a vector of Modifier objects. + */ std::vector Modifier::getList () { @@ -58,7 +61,21 @@ Modifier::getList () { return modifiers; }; -} // namespace Modifier +/** + * Test if this modifier is currently active. + * + * @param button_state - The GDK button state from an event + * @return a boolean, true if the modifiers for this action are active. + */ +bool Modifier::active(int button_state) +{ + // TODO: + // * ALT key is sometimes MOD1, MOD2 etc, if we find other ALT keys, set the ALT bit + // * SUPER key could be HYPER or META, these cases need to be considered. + return get_and_mask() & button_state; +} + +} // namespace Modifiers } // namespace Inkscape /* diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 46c0035c9d..c5ed9c6185 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -9,19 +9,21 @@ #include #include -#include #include -//#include +#include + +#include namespace Inkscape { -namespace Modifier { +namespace Modifiers { using KeyMask = int; KeyMask NON_USER = -1; -KeyMask SHIFT = 1; // GDK_SHIFT_MASK; -KeyMask CTRL = 4; // GDK_CONTROL_MASK; -KeyMask ALT = 8; // GDK_MOD1_MASK; +KeyMask SHIFT = GDK_SHIFT_MASK; +KeyMask CTRL = GDK_CONTROL_MASK; +KeyMask ALT = GDK_MOD1_MASK; +KeyMask SUPER = GDK_SUPER_MASK; /** * This anonymous enum is used to provide a list of the Shifts @@ -77,10 +79,12 @@ private: char const * _name; // A descriptive name used in preferences UI char const * _desc; // A more verbose description used in preferences UI //char const * _group; // Optional group for preferences UI - KeyMask _default; // The default value if nothing set in keys.xml - // User set data - KeyMask _value = NON_USER; // The value set by keys.xml + // Default values if nothing is set in keys.xml + KeyMask _and_mask_default; // The pressed keys must have these bits set + + // User set data, set by keys.xml (or other included file) + KeyMask _and_mask_user = NON_USER; protected: @@ -93,16 +97,18 @@ public: //char const * get_group() const { return _group; } // Set user value - bool is_user_set() const { return _value != NON_USER; } - void set_value (KeyMask value) { _value = value; } - void unset_value() { _value = NON_USER; } + bool is_set() const { return _and_mask_user != NON_USER; } + void set(KeyMask and_mask) { + _and_mask_user = and_mask; + } + void unset() { set(NON_USER); } // Get value, either user defined value or default - const KeyMask get_value() { - if(is_user_set()) { - return _value; + const KeyMask get_and_mask() { + if(_and_mask_user != NON_USER) { + return _and_mask_user; } - return _default; + return _and_mask_default; } /** @@ -118,20 +124,20 @@ public: char const * id, char const * name, char const * desc, - const KeyMask default_) : + const KeyMask and_mask) : _index(index), _id(id), _name(name), _desc(desc), - _default(default_) + _and_mask_default(and_mask) { _modifier_lookup.emplace(_id, this); } // Delete the destructor, because we are eternal ~Modifier() = delete; - static void list (); - static std::vectorgetList (); + static std::vectorgetList (); + bool active(int button_state); /** * A function to turn an enum index into a modifier object. @@ -161,8 +167,9 @@ public: }; // Modifier class -} // Modifier namespace -} // Inkscape namespace +} // namespace Modifiers +} // namespace Inkscape + #endif // SEEN_SP_MODIFIERS_H diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 0f5c7520a6..d62252bba6 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -45,6 +45,7 @@ #include "object/box3d.h" #include "style.h" +#include "ui/modifiers.h" #include "ui/pixmaps/cursor-select-d.xpm" #include "ui/pixmaps/cursor-select-m.xpm" #include "ui/pixmaps/handles.xpm" @@ -60,6 +61,7 @@ using Inkscape::DocumentUndo; +using Inkscape::Modifiers::Modifier; GdkPixbuf *handles[23]; @@ -515,7 +517,8 @@ bool SelectTool::root_handler(GdkEvent* event) { Geom::Point const button_pt(event->button.x, event->button.y); Geom::Point const p(desktop->w2d(button_pt)); - if (event->button.state & GDK_MOD1_MASK) { + if(Modifier::get(Modifiers::SELECT_TOUCH_PATH)->active(event->button.state)) { + //if (event->button.state & GDK_MOD1_MASK) { Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH); } @@ -551,6 +554,10 @@ bool SelectTool::root_handler(GdkEvent* event) { { tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); + bool first_hit = Modifier::get(Modifiers::SELECT_FIRST_HIT)->active(this->button_press_state); + bool touch_path = Modifier::get(Modifiers::SELECT_TOUCH_PATH)->active(this->button_press_state); + bool always_box = Modifier::get(Modifiers::SELECT_ALWAYS_BOX)->active(this->button_press_state); + if ((event->motion.state & GDK_BUTTON1_MASK) && !this->space_panning) { Geom::Point const motion_pt(event->motion.x, event->motion.y); Geom::Point const p(desktop->w2d(motion_pt)); @@ -564,7 +571,8 @@ bool SelectTool::root_handler(GdkEvent* event) { // motion notify coordinates as given (no snapping back to origin) within_tolerance = false; - if ((this->button_press_state & GDK_CONTROL_MASK) || ((this->button_press_state & GDK_MOD1_MASK) && !(this->button_press_state & GDK_SHIFT_MASK) && !selection->isEmpty())) { + if(first_hit || (touch_path || !(always_box) && !selection->isEmpty())) { + //if ((this->button_press_state & GDK_CONTROL_MASK) || ((this->button_press_state & GDK_MOD1_MASK) && !(this->button_press_state & GDK_SHIFT_MASK) && !selection->isEmpty())) { // if it's not click and ctrl or alt was pressed (the latter with some selection // but not with shift) we want to drag rather than rubberband this->dragging = TRUE; @@ -589,7 +597,8 @@ bool SelectTool::root_handler(GdkEvent* event) { item_at_point = desktop->getItemAtPoint(Geom::Point(xp, yp), FALSE); } - if (item_at_point || this->moved || this->button_press_state & GDK_MOD1_MASK) { + if (item_at_point || this->moved || touch_path) { + //if (item_at_point || this->moved || this->button_press_state & GDK_MOD1_MASK) { // drag only if starting from an item, or if something is already grabbed, or if alt-dragging if (!this->moved) { item_in_group = desktop->getItemAtPoint(Geom::Point(event->button.x, event->button.y), TRUE); @@ -613,7 +622,8 @@ bool SelectTool::root_handler(GdkEvent* event) { // if neither a group nor an item (possibly in a group) at point are selected, set selection to the item at point if ((!item_in_group || !selection->includes(item_in_group)) && (!group_at_point || !selection->includes(group_at_point)) - && !(this->button_press_state & GDK_MOD1_MASK)) { + && !touch_path) { +// && !(this->button_press_state & GDK_MOD1_MASK)) { // select what is under cursor if (!_seltrans->isEmpty()) { _seltrans->resetState(); @@ -676,7 +686,8 @@ bool SelectTool::root_handler(GdkEvent* event) { } else if (this->item && !drag_escaped) { // item has not been moved -> simply a click, do selecting if (!selection->isEmpty()) { - if (event->button.state & GDK_SHIFT_MASK) { + if(Modifier::get(Modifiers::SELECT_ADD_TO)->active(event->button.state)) { +// if (event->button.state & GDK_SHIFT_MASK) { // with shift, toggle selection _seltrans->resetState(); selection->toggle(this->item); -- GitLab From 1f258ba556ca378cae0f4e2e4688879bd7de7ad7 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 11 Jun 2020 09:24:05 -0400 Subject: [PATCH 07/24] Turn vector into map and upgrade Type to a class enum --- src/ui/modifiers.cpp | 38 +++++++++++++++++++----------------- src/ui/modifiers.h | 35 ++++++++++++--------------------- src/ui/tools/select-tool.cpp | 10 +++++----- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index fd273ed4ce..60dfc64306 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -20,28 +20,30 @@ namespace Inkscape { namespace Modifiers { +Modifier::Lookup Modifier::_modifier_lookup; + // these must be in the same order as the * enum in "modifers.h" -Modifier *Modifier::_modifiers[] = { +decltype(Modifier::_modifiers) Modifier::_modifiers { // Canvas modifiers - new Modifier(CANVAS_SCROLL_Y, "canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0), - new Modifier(CANVAS_SCROLL_X, "canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT), - new Modifier(CANVAS_ZOOM, "canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL), - new Modifier(CANVAS_ROTATE, "canvas-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL), + {Type::CANVAS_SCROLL_Y, new Modifier("canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0)}, + {Type::CANVAS_SCROLL_X, new Modifier("canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT)}, + {Type::CANVAS_ZOOM, new Modifier("canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL)}, + {Type::CANVAS_ROTATE, new Modifier("canvs-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL)}, // Select tool modifiers (minus transforms) - new Modifier(SELECT_ADD_TO, "select-add-to", "Add to selection", "Add items to existing selection", SHIFT), - new Modifier(SELECT_IN_GROUPS, "select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL), - new Modifier(SELECT_TOUCH_PATH, "select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT), - new Modifier(SELECT_ALWAYS_BOX, "select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT), - new Modifier(SELECT_FIRST_HIT, "select-first-hit", "Select the first", "Scroll up and down", CTRL), + {Type::SELECT_ADD_TO, new Modifier("select-add-to", "Add to selection", "Add items to existing selection", SHIFT)}, + {Type::SELECT_IN_GROUPS, new Modifier("select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL)}, + {Type::SELECT_TOUCH_PATH, new Modifier("select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT)}, + {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT)}, + {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Scroll up and down", CTRL)}, // Transform handle modifiers (applies to multiple tools) - new Modifier(MOVE_AXIS_CONFINE, "move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL), - new Modifier(SCALE_RATIO_CONFINE, "scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL), - new Modifier(SCALE_FROM_CENTER, "scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT), - new Modifier(SCALE_FIXED_RATIO, "scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT), - new Modifier(TRANS_FIXED_RATIO, "trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL), - new Modifier(TRANS_OFF_CENTER, "trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT), + {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL)}, + {Type::SCALE_RATIO_CONFINE, new Modifier("scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL)}, + {Type::SCALE_FROM_CENTER, new Modifier("scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT)}, + {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT)}, + {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL)}, + {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT)}, }; /** @@ -54,8 +56,8 @@ Modifier::getList () { std::vector modifiers; // Go through the dynamic modifier table - for (Modifier * modifier : _modifiers) { - modifiers.push_back(modifier); + for( auto const& [key, val] : _modifiers ) { + modifiers.push_back(val); } return modifiers; diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index c5ed9c6185..9156d189b8 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -19,16 +19,18 @@ namespace Modifiers { using KeyMask = int; -KeyMask NON_USER = -1; -KeyMask SHIFT = GDK_SHIFT_MASK; -KeyMask CTRL = GDK_CONTROL_MASK; -KeyMask ALT = GDK_MOD1_MASK; -KeyMask SUPER = GDK_SUPER_MASK; +enum Key : KeyMask { + NON_USER = -1, + SHIFT = GDK_SHIFT_MASK, + CTRL = GDK_CONTROL_MASK, + ALT = GDK_MOD1_MASK, + SUPER = GDK_SUPER_MASK, +}; /** * This anonymous enum is used to provide a list of the Shifts */ -enum Type { +enum class Type { // {TOOL_NAME}_{ACTION_NAME} // Canvas tools (applies to any tool selection) @@ -52,9 +54,6 @@ enum Type { TRANS_FIXED_RATIO, // Rotate/skew by fixed ratio angles {HANDLE+CTRL} TRANS_OFF_CENTER, // Rotate/skew from oposite corner {HANDLE+SHIFT} // TODO: Alignment ommitted because it's UX is not completed - - /* Footer */ - LAST }; @@ -63,18 +62,14 @@ enum Type { */ class Modifier { private: - /** An easy to use definition of the table of modifiers by ID. */ + /** An easy to use definition of the table of modifiers by Type and ID. */ + typedef std::map Container; typedef std::map Lookup; - /** A table of all the created modifers. */ + /** A table of all the created modifers and their ID lookups. */ + static Container _modifiers; static Lookup _modifier_lookup; - static Modifier * _modifiers[LAST + 1]; - /* Plus one because there is an entry for LAST */ - - // Fixed data defined in code and created at run time - - Type _index; // Index of the modifier, based on the modifier enum char const * _id; // A unique id used by keys.xml to identify it char const * _name; // A descriptive name used in preferences UI char const * _desc; // A more verbose description used in preferences UI @@ -90,7 +85,6 @@ protected: public: - const Type get_index() const { return _index; } char const * get_id() const { return _id; } char const * get_name() const { return _name; } char const * get_description() const { return _desc; } @@ -114,18 +108,15 @@ public: /** * Inititalizes the Modifier with the parameters. * - * @param index Goes to \c _index. * @param id Goes to \c _id. * @param name Goes to \c _name. * @param desc Goes to \c _desc. * @param default_ Goes to \c _default. */ - Modifier(Type index, - char const * id, + Modifier(char const * id, char const * name, char const * desc, const KeyMask and_mask) : - _index(index), _id(id), _name(name), _desc(desc), diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index d62252bba6..c101f30244 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -517,7 +517,7 @@ bool SelectTool::root_handler(GdkEvent* event) { Geom::Point const button_pt(event->button.x, event->button.y); Geom::Point const p(desktop->w2d(button_pt)); - if(Modifier::get(Modifiers::SELECT_TOUCH_PATH)->active(event->button.state)) { + if(Modifier::get(Modifiers::Type::SELECT_TOUCH_PATH)->active(event->button.state)) { //if (event->button.state & GDK_MOD1_MASK) { Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH); } @@ -554,9 +554,9 @@ bool SelectTool::root_handler(GdkEvent* event) { { tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); - bool first_hit = Modifier::get(Modifiers::SELECT_FIRST_HIT)->active(this->button_press_state); - bool touch_path = Modifier::get(Modifiers::SELECT_TOUCH_PATH)->active(this->button_press_state); - bool always_box = Modifier::get(Modifiers::SELECT_ALWAYS_BOX)->active(this->button_press_state); + bool first_hit = Modifier::get(Modifiers::Type::SELECT_FIRST_HIT)->active(this->button_press_state); + bool touch_path = Modifier::get(Modifiers::Type::SELECT_TOUCH_PATH)->active(this->button_press_state); + bool always_box = Modifier::get(Modifiers::Type::SELECT_ALWAYS_BOX)->active(this->button_press_state); if ((event->motion.state & GDK_BUTTON1_MASK) && !this->space_panning) { Geom::Point const motion_pt(event->motion.x, event->motion.y); @@ -686,7 +686,7 @@ bool SelectTool::root_handler(GdkEvent* event) { } else if (this->item && !drag_escaped) { // item has not been moved -> simply a click, do selecting if (!selection->isEmpty()) { - if(Modifier::get(Modifiers::SELECT_ADD_TO)->active(event->button.state)) { + if(Modifier::get(Modifiers::Type::SELECT_ADD_TO)->active(event->button.state)) { // if (event->button.state & GDK_SHIFT_MASK) { // with shift, toggle selection _seltrans->resetState(); -- GitLab From 4be68d8e20b99c78bb53749bd63b03e0c4884902 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 11 Jun 2020 09:55:48 -0400 Subject: [PATCH 08/24] Fix force_drag and apply more modifiers --- src/ui/modifiers.cpp | 3 ++- src/ui/modifiers.h | 3 ++- src/ui/tools/select-tool.cpp | 38 +++++++++++++++--------------------- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 60dfc64306..9512eeca1e 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -35,7 +35,8 @@ decltype(Modifier::_modifiers) Modifier::_modifiers { {Type::SELECT_IN_GROUPS, new Modifier("select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL)}, {Type::SELECT_TOUCH_PATH, new Modifier("select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT)}, {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT)}, - {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Scroll up and down", CTRL)}, + {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Drag the first item the mouse hits", CTRL)}, + {Type::SELECT_FORCE_DRAG, new Modifier("select-force-drag", "Forced Drag", "Drag objects even if the mouse isn't over them.", ALT)}, // Transform handle modifiers (applies to multiple tools) {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL)}, diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 9156d189b8..887c4ad4ae 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -42,9 +42,10 @@ enum class Type { // Select tool (minus transform) SELECT_ADD_TO, // Add selection {SHIFT+CLICK} SELECT_IN_GROUPS, // Select within groups {CTRL+CLICK} - SELECT_TOUCH_PATH, // Draw band to select {ALT+DRAG} + SELECT_TOUCH_PATH, // Draw band to select {ALT+DRAG+Nothing selected} SELECT_ALWAYS_BOX, // Draw box to select {SHIFT+DRAG} SELECT_FIRST_HIT, // Start dragging first item hit {CTRL+DRAG} (Is this an actual feature?) + SELECT_FORCE_DRAG, // Drag objects even if the mouse isn't over them {ALT+DRAG+Selected} // Transform handles (applies to multiple tools) MOVE_AXIS_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index c101f30244..5fe8d6ac18 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -518,7 +518,6 @@ bool SelectTool::root_handler(GdkEvent* event) { Geom::Point const p(desktop->w2d(button_pt)); if(Modifier::get(Modifiers::Type::SELECT_TOUCH_PATH)->active(event->button.state)) { - //if (event->button.state & GDK_MOD1_MASK) { Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH); } @@ -555,7 +554,7 @@ bool SelectTool::root_handler(GdkEvent* event) { tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); bool first_hit = Modifier::get(Modifiers::Type::SELECT_FIRST_HIT)->active(this->button_press_state); - bool touch_path = Modifier::get(Modifiers::Type::SELECT_TOUCH_PATH)->active(this->button_press_state); + bool force_drag = Modifier::get(Modifiers::Type::SELECT_FORCE_DRAG)->active(this->button_press_state); bool always_box = Modifier::get(Modifiers::Type::SELECT_ALWAYS_BOX)->active(this->button_press_state); if ((event->motion.state & GDK_BUTTON1_MASK) && !this->space_panning) { @@ -571,8 +570,7 @@ bool SelectTool::root_handler(GdkEvent* event) { // motion notify coordinates as given (no snapping back to origin) within_tolerance = false; - if(first_hit || (touch_path || !(always_box) && !selection->isEmpty())) { - //if ((this->button_press_state & GDK_CONTROL_MASK) || ((this->button_press_state & GDK_MOD1_MASK) && !(this->button_press_state & GDK_SHIFT_MASK) && !selection->isEmpty())) { + if (first_hit || (force_drag && !always_box && !selection->isEmpty())) { // if it's not click and ctrl or alt was pressed (the latter with some selection // but not with shift) we want to drag rather than rubberband this->dragging = TRUE; @@ -597,8 +595,7 @@ bool SelectTool::root_handler(GdkEvent* event) { item_at_point = desktop->getItemAtPoint(Geom::Point(xp, yp), FALSE); } - if (item_at_point || this->moved || touch_path) { - //if (item_at_point || this->moved || this->button_press_state & GDK_MOD1_MASK) { + if (item_at_point || this->moved || force_drag) { // drag only if starting from an item, or if something is already grabbed, or if alt-dragging if (!this->moved) { item_in_group = desktop->getItemAtPoint(Geom::Point(event->button.x, event->button.y), TRUE); @@ -621,9 +618,7 @@ bool SelectTool::root_handler(GdkEvent* event) { // if neither a group nor an item (possibly in a group) at point are selected, set selection to the item at point if ((!item_in_group || !selection->includes(item_in_group)) && - (!group_at_point || !selection->includes(group_at_point)) - && !touch_path) { -// && !(this->button_press_state & GDK_MOD1_MASK)) { + (!group_at_point || !selection->includes(group_at_point)) && !force_drag) { // select what is under cursor if (!_seltrans->isEmpty()) { _seltrans->resetState(); @@ -687,7 +682,6 @@ bool SelectTool::root_handler(GdkEvent* event) { // item has not been moved -> simply a click, do selecting if (!selection->isEmpty()) { if(Modifier::get(Modifiers::Type::SELECT_ADD_TO)->active(event->button.state)) { -// if (event->button.state & GDK_SHIFT_MASK) { // with shift, toggle selection _seltrans->resetState(); selection->toggle(this->item); @@ -739,7 +733,7 @@ bool SelectTool::root_handler(GdkEvent* event) { r->stop(); this->defaultMessageContext()->clear(); - if (event->button.state & GDK_SHIFT_MASK) { + if(Modifier::get(Modifiers::Type::SELECT_ADD_TO)->active(event->button.state)) { // with shift, add to selection selection->addList (items); } else { @@ -750,21 +744,21 @@ bool SelectTool::root_handler(GdkEvent* event) { } else { // it was just a click, or a too small rubberband r->stop(); - bool shift_release = (event->button.state & GDK_SHIFT_MASK) ? true : false; - bool ctrl_release = (event->button.state & GDK_CONTROL_MASK) ? true : false; - bool alt_release = (event->button.state & GDK_MOD1_MASK) ? true : false; + bool add_to = Modifier::get(Modifiers::Type::SELECT_ADD_TO)->active(event->button.state); + bool in_groups = Modifier::get(Modifiers::Type::SELECT_IN_GROUPS)->active(event->button.state); + bool force_drag = Modifier::get(Modifiers::Type::SELECT_FORCE_DRAG)->active(event->button.state); - if (shift_release && !rb_escaped && !drag_escaped) { + if (add_to && !rb_escaped && !drag_escaped) { // this was a shift+click or alt+shift+click, select what was clicked upon - if (ctrl_release) { - // go into groups, honoring Alt + if (in_groups) { + // go into groups, honoring force_drag (Alt) item = sp_event_context_find_item (desktop, - Geom::Point(event->button.x, event->button.y), event->button.state & GDK_MOD1_MASK, TRUE); + Geom::Point(event->button.x, event->button.y), force_drag, TRUE); } else { // don't go into groups, honoring Alt item = sp_event_context_find_item (desktop, - Geom::Point(event->button.x, event->button.y), event->button.state & GDK_MOD1_MASK, FALSE); + Geom::Point(event->button.x, event->button.y), force_drag, FALSE); } if (item) { @@ -772,9 +766,9 @@ bool SelectTool::root_handler(GdkEvent* event) { item = nullptr; } - } else if ((ctrl_release || alt_release) && !rb_escaped && !drag_escaped) { // ctrl+click, alt+click + } else if ((in_groups || force_drag) && !rb_escaped && !drag_escaped) { // ctrl+click, alt+click item = sp_event_context_find_item (desktop, - Geom::Point(event->button.x, event->button.y), alt_release, ctrl_release); + Geom::Point(event->button.x, event->button.y), force_drag, in_groups); if (item) { if (selection->includes(item)) { @@ -788,7 +782,7 @@ bool SelectTool::root_handler(GdkEvent* event) { } } else { // click without shift, simply deselect, unless with Alt or something was cancelled if (!selection->isEmpty()) { - if (!(rb_escaped) && !(drag_escaped) && !(alt_release)) { + if (!(rb_escaped) && !(drag_escaped) && !force_drag) { selection->clear(); } -- GitLab From cff02a9794dbebbba1f3b1593a147f0cda8cc6d0 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 11 Jun 2020 14:49:06 -0400 Subject: [PATCH 09/24] Can't produce pathway that call into this code or find original bug --- src/ui/tools/select-tool.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 5fe8d6ac18..d9c6414f51 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -208,11 +208,6 @@ bool SelectTool::sp_select_context_abort() { } sp_object_unref( this->item, nullptr); - } else if (this->button_press_state & GDK_CONTROL_MASK) { - // NOTE: This is a workaround to a bug. - // When the ctrl key is held, sc->item is not defined - // so in this case (only), we skip the object doc check - DocumentUndo::undo(desktop->getDocument()); } this->item = nullptr; -- GitLab From 4e97d9e250a9800063552598be57d0791571944d Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 11 Jun 2020 14:53:03 -0400 Subject: [PATCH 10/24] Add remaining select-tool modifiers --- src/ui/modifiers.cpp | 1 + src/ui/modifiers.h | 1 + src/ui/tools/select-tool.cpp | 27 ++++++++++++++------------- src/ui/tools/select-tool.h | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 9512eeca1e..57aa266a40 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -37,6 +37,7 @@ decltype(Modifier::_modifiers) Modifier::_modifiers { {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT)}, {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Drag the first item the mouse hits", CTRL)}, {Type::SELECT_FORCE_DRAG, new Modifier("select-force-drag", "Forced Drag", "Drag objects even if the mouse isn't over them.", ALT)}, + {Type::SELECT_CYCLE, new Modifier("select-cycle", "Cycle through objects", "Scroll through objects under the cursor.", ALT)}, // Transform handle modifiers (applies to multiple tools) {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL)}, diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 887c4ad4ae..803c9ec6e2 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -46,6 +46,7 @@ enum class Type { SELECT_ALWAYS_BOX, // Draw box to select {SHIFT+DRAG} SELECT_FIRST_HIT, // Start dragging first item hit {CTRL+DRAG} (Is this an actual feature?) SELECT_FORCE_DRAG, // Drag objects even if the mouse isn't over them {ALT+DRAG+Selected} + SELECT_CYCLE, // Cycle through objects under cursor {ALT+SCROLL} // Transform handles (applies to multiple tools) MOVE_AXIS_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index d9c6414f51..2e5394af8d 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -292,27 +292,28 @@ bool SelectTool::item_handler(SPItem* item, GdkEvent* event) { // remember what modifiers were on before button press this->button_press_state = event->button.state; + bool first_hit = Modifier::get(Modifiers::Type::SELECT_FIRST_HIT)->active(this->button_press_state); + bool force_drag = Modifier::get(Modifiers::Type::SELECT_FORCE_DRAG)->active(this->button_press_state); + bool always_box = Modifier::get(Modifiers::Type::SELECT_ALWAYS_BOX)->active(this->button_press_state); + + // if shift or ctrl was pressed, do not move objects; + // pass the event to root handler which will perform rubberband, shift-click, ctrl-click, ctrl-drag + if (!(always_box || first_hit)) { - if (event->button.state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) { - // if shift or ctrl was pressed, do not move objects; - // pass the event to root handler which will perform rubberband, shift-click, ctrl-click, ctrl-drag - } else { GdkWindow* window = gtk_widget_get_window (GTK_WIDGET (desktop->getCanvas()->gobj())); - + this->dragging = TRUE; this->moved = FALSE; gdk_window_set_cursor(window, CursorSelectDragging); - // remember the clicked item in this->item: if (this->item) { sp_object_unref(this->item, nullptr); this->item = nullptr; } - this->item = sp_event_context_find_item (desktop, - Geom::Point(event->button.x, event->button.y), event->button.state & GDK_MOD1_MASK, FALSE); + this->item = sp_event_context_find_item (desktop, Geom::Point(event->button.x, event->button.y), force_drag, FALSE); sp_object_ref(this->item, nullptr); rb_escaped = drag_escaped = 0; @@ -384,7 +385,7 @@ bool SelectTool::item_handler(SPItem* item, GdkEvent* event) { return ret; } -void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *selection, GdkEventScroll *scroll_event, bool shift_pressed) { +void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *selection, GdkEventScroll *scroll_event) { if ( this->cycling_items.empty() ) return; @@ -441,7 +442,7 @@ void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *sele arenaitem = cycling_cur_item->get_arenaitem(desktop->dkey); arenaitem->setOpacity(1.0); - if (shift_pressed) { + if (Modifier::get(Modifiers::Type::SELECT_ADD_TO)->active(scroll_event->state)) { selection->add(cycling_cur_item); } else { selection->set(cycling_cur_item); @@ -807,10 +808,10 @@ bool SelectTool::root_handler(GdkEvent* event) { GdkEventScroll *scroll_event = (GdkEventScroll*) event; - if ( ! (scroll_event->state & GDK_MOD1_MASK)) // do nothing specific if alt was not pressed + // do nothing specific if alt was not pressed + if ( ! Modifier::get(Modifiers::Type::SELECT_CYCLE)->active(scroll_event->state)) break; - bool shift_pressed = scroll_event->state & GDK_SHIFT_MASK; is_cycling = true; /* Rebuild list of items underneath the mouse pointer */ @@ -847,7 +848,7 @@ bool SelectTool::root_handler(GdkEvent* event) { this->cycling_wrap = prefs->getBool("/options/selection/cycleWrap", true); // Cycle through the items underneath the mouse pointer, one-by-one - this->sp_select_context_cycle_through_items(selection, scroll_event, shift_pressed); + this->sp_select_context_cycle_through_items(selection, scroll_event); ret = TRUE; diff --git a/src/ui/tools/select-tool.h b/src/ui/tools/select-tool.h index 9fe85492f4..d59da02942 100644 --- a/src/ui/tools/select-tool.h +++ b/src/ui/tools/select-tool.h @@ -59,7 +59,7 @@ public: private: bool sp_select_context_abort(); - void sp_select_context_cycle_through_items(Inkscape::Selection *selection, GdkEventScroll *scroll_event, bool shift_pressed); + void sp_select_context_cycle_through_items(Inkscape::Selection *selection, GdkEventScroll *scroll_event); void sp_select_context_reset_opacities(); }; -- GitLab From 85c81acd956be628926b5c1311e096b198a50b35 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 11 Jun 2020 14:53:37 -0400 Subject: [PATCH 11/24] Make first attempt at recording trigger types for collision detection --- src/ui/modifiers.cpp | 32 ++++++++++++++++---------------- src/ui/modifiers.h | 15 +++++++++++---- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 57aa266a40..7ef47cd1bd 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -25,27 +25,27 @@ Modifier::Lookup Modifier::_modifier_lookup; // these must be in the same order as the * enum in "modifers.h" decltype(Modifier::_modifiers) Modifier::_modifiers { // Canvas modifiers - {Type::CANVAS_SCROLL_Y, new Modifier("canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0)}, - {Type::CANVAS_SCROLL_X, new Modifier("canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT)}, - {Type::CANVAS_ZOOM, new Modifier("canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL)}, - {Type::CANVAS_ROTATE, new Modifier("canvs-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL)}, + {Type::CANVAS_SCROLL_Y, new Modifier("canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0, SCROLL)}, + {Type::CANVAS_SCROLL_X, new Modifier("canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT, SCROLL)}, + {Type::CANVAS_ZOOM, new Modifier("canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL, SCROLL)}, + {Type::CANVAS_ROTATE, new Modifier("canvs-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL, SCROLL)}, // Select tool modifiers (minus transforms) - {Type::SELECT_ADD_TO, new Modifier("select-add-to", "Add to selection", "Add items to existing selection", SHIFT)}, - {Type::SELECT_IN_GROUPS, new Modifier("select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL)}, - {Type::SELECT_TOUCH_PATH, new Modifier("select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT)}, - {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT)}, - {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Drag the first item the mouse hits", CTRL)}, - {Type::SELECT_FORCE_DRAG, new Modifier("select-force-drag", "Forced Drag", "Drag objects even if the mouse isn't over them.", ALT)}, + {Type::SELECT_ADD_TO, new Modifier("select-add-to", "Add to selection", "Add items to existing selection", SHIFT, CLICK)}, + {Type::SELECT_IN_GROUPS, new Modifier("select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL, CLICK)}, + {Type::SELECT_TOUCH_PATH, new Modifier("select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT, DRAG)}, + {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT, DRAG)}, + {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Drag the first item the mouse hits", CTRL, DRAG)}, + {Type::SELECT_FORCE_DRAG, new Modifier("select-force-drag", "Forced Drag", "Drag objects even if the mouse isn't over them.", ALT, DRAG)}, {Type::SELECT_CYCLE, new Modifier("select-cycle", "Cycle through objects", "Scroll through objects under the cursor.", ALT)}, // Transform handle modifiers (applies to multiple tools) - {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL)}, - {Type::SCALE_RATIO_CONFINE, new Modifier("scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL)}, - {Type::SCALE_FROM_CENTER, new Modifier("scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT)}, - {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT)}, - {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL)}, - {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT)}, + {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL, HANDLE)}, + {Type::SCALE_RATIO_CONFINE, new Modifier("scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL, HANDLE)}, + {Type::SCALE_FROM_CENTER, new Modifier("scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT, HANDLE)}, + {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT, HANDLE)}, + {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL, HANDLE)}, + {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT, HANDLE)}, }; /** diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 803c9ec6e2..f0ba35d28c 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -18,6 +18,7 @@ namespace Inkscape { namespace Modifiers { using KeyMask = int; +using Trigger = int; enum Key : KeyMask { NON_USER = -1, @@ -26,6 +27,9 @@ enum Key : KeyMask { ALT = GDK_MOD1_MASK, SUPER = GDK_SUPER_MASK, }; +// Triggers used for collision warnings, two tools are using the same trigger +enum Triggers : Trigger {CLICK, DRAG, SCROLL, HANDLE}; +// TODO: We may want to further define the tool, from ANY, SELECT, NODE etc. /** * This anonymous enum is used to provide a list of the Shifts @@ -75,7 +79,8 @@ private: char const * _id; // A unique id used by keys.xml to identify it char const * _name; // A descriptive name used in preferences UI char const * _desc; // A more verbose description used in preferences UI - //char const * _group; // Optional group for preferences UI + + Trigger _trigger; // The type of trigger used for collisions // Default values if nothing is set in keys.xml KeyMask _and_mask_default; // The pressed keys must have these bits set @@ -90,7 +95,7 @@ public: char const * get_id() const { return _id; } char const * get_name() const { return _name; } char const * get_description() const { return _desc; } - //char const * get_group() const { return _group; } + const Trigger get_trigger() const { return _trigger; } // Set user value bool is_set() const { return _and_mask_user != NON_USER; } @@ -118,11 +123,13 @@ public: Modifier(char const * id, char const * name, char const * desc, - const KeyMask and_mask) : + const KeyMask and_mask, + const Trigger trigger) : _id(id), _name(name), _desc(desc), - _and_mask_default(and_mask) + _and_mask_default(and_mask), + _trigger(trigger) { _modifier_lookup.emplace(_id, this); } -- GitLab From 3690b8b16113e69867ff1f7e5fa4e76879bad261 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Tue, 7 Jul 2020 11:47:01 -0400 Subject: [PATCH 12/24] Remove super-seeded wheelzoom option. --- src/display/control/canvas-item-drawing.cpp | 4 +--- src/preferences-skeleton.h | 1 - src/ui/dialog/inkscape-preferences.cpp | 3 --- src/ui/dialog/inkscape-preferences.h | 1 - src/ui/modifiers.cpp | 2 +- src/ui/tools/tool-base.cpp | 3 +-- 6 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/display/control/canvas-item-drawing.cpp b/src/display/control/canvas-item-drawing.cpp index 5ecb5fdb6f..22e5f0590c 100644 --- a/src/display/control/canvas-item-drawing.cpp +++ b/src/display/control/canvas-item-drawing.cpp @@ -255,10 +255,8 @@ bool CanvasItemDrawing::handle_event(GdkEvent *event) case GDK_SCROLL: { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool wheelzooms = prefs->getBool("/options/wheelzooms/value"); bool ctrl = (event->scroll.state & GDK_CONTROL_MASK); - if ((ctrl && !wheelzooms) || (!ctrl && wheelzooms)) { + if (ctrl) { /* Zoom is emitted by the canvas as well, ignore here */ return false; } diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index 9bfd660538..e2a355f506 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -278,7 +278,6 @@ R"=====( - diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 76bcc68214..48eea74b66 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1881,9 +1881,6 @@ void InkscapePreferences::initPageBehavior() _scroll_space.init ( _("Mouse move pans when Space is pressed"), "/options/spacebarpans/value", true); _page_scrolling.add_line( true, "", _scroll_space, "", _("When on, pressing and holding Space and dragging pans canvas")); - _wheel_zoom.init ( _("Mouse wheel zooms by default"), "/options/wheelzooms/value", false); - _page_scrolling.add_line( false, "", _wheel_zoom, "", - _("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl")); this->AddPage(_page_scrolling, _("Scrolling"), iter_behavior, PREFS_PAGE_BEHAVIOR_SCROLLING); // Snapping options diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 7e785e2658..a12a52f1c2 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -190,7 +190,6 @@ protected: UI::Widget::PrefSpinButton _scroll_auto_speed; UI::Widget::PrefSpinButton _scroll_auto_thres; UI::Widget::PrefCheckButton _scroll_space; - UI::Widget::PrefCheckButton _wheel_zoom; Gtk::Scale *_slider_snapping_delay; diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 7ef47cd1bd..393c31f890 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -37,7 +37,7 @@ decltype(Modifier::_modifiers) Modifier::_modifiers { {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT, DRAG)}, {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Drag the first item the mouse hits", CTRL, DRAG)}, {Type::SELECT_FORCE_DRAG, new Modifier("select-force-drag", "Forced Drag", "Drag objects even if the mouse isn't over them.", ALT, DRAG)}, - {Type::SELECT_CYCLE, new Modifier("select-cycle", "Cycle through objects", "Scroll through objects under the cursor.", ALT)}, + {Type::SELECT_CYCLE, new Modifier("select-cycle", "Cycle through objects", "Scroll through objects under the cursor.", ALT, SCROLL)}, // Transform handle modifiers (applies to multiple tools) {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL, HANDLE)}, diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp index c5033f1d31..334a60eca3 100644 --- a/src/ui/tools/tool-base.cpp +++ b/src/ui/tools/tool-base.cpp @@ -740,7 +740,6 @@ bool ToolBase::root_handler(GdkEvent* event) { case GDK_SCROLL: { bool ctrl = (event->scroll.state & GDK_CONTROL_MASK); bool shift = (event->scroll.state & GDK_SHIFT_MASK); - bool wheelzooms = prefs->getBool("/options/wheelzooms/value"); int constexpr WHEEL_SCROLL_DEFAULT = 40; int const wheel_scroll = prefs->getIntLimited( @@ -815,7 +814,7 @@ bool ToolBase::root_handler(GdkEvent* event) { break; } - } else if ((ctrl && !wheelzooms) || (!ctrl && wheelzooms)) { + } else if (ctrl) { /* ctrl + wheel, zoom in--out */ double rel_zoom; double const zoom_inc = prefs->getDoubleLimited( -- GitLab From 4ef7454a4e36528cd7025072a946a5a8e627c775 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Tue, 7 Jul 2020 14:59:53 -0400 Subject: [PATCH 13/24] Apply canvas modifiers as needed --- src/display/control/canvas-item-drawing.cpp | 4 ++-- src/ui/tools/tool-base.cpp | 24 +++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/display/control/canvas-item-drawing.cpp b/src/display/control/canvas-item-drawing.cpp index 22e5f0590c..a9919a7eb9 100644 --- a/src/display/control/canvas-item-drawing.cpp +++ b/src/display/control/canvas-item-drawing.cpp @@ -26,6 +26,7 @@ #include "display/drawing-surface.h" #include "ui/widget/canvas.h" +#include "ui/modifiers.h" namespace Inkscape { @@ -255,8 +256,7 @@ bool CanvasItemDrawing::handle_event(GdkEvent *event) case GDK_SCROLL: { - bool ctrl = (event->scroll.state & GDK_CONTROL_MASK); - if (ctrl) { + if (Modifiers::Modifier::get(Modifiers::Type::CANVAS_ZOOM)->active(event->scroll.state)) { /* Zoom is emitted by the canvas as well, ignore here */ return false; } diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp index 334a60eca3..1f6598a7f4 100644 --- a/src/ui/tools/tool-base.cpp +++ b/src/ui/tools/tool-base.cpp @@ -41,6 +41,7 @@ #include "object/sp-guide.h" +#include "ui/modifiers.h" #include "ui/contextmenu.h" #include "ui/interface.h" #include "ui/event-debug.h" @@ -333,6 +334,11 @@ bool ToolBase::root_handler(GdkEvent* event) { bool allow_panning = prefs->getBool("/options/spacebarpans/value"); gint ret = FALSE; + bool mod_rotate = Modifiers::Modifier::get(Modifiers::Type::CANVAS_ROTATE)->active(event->scroll.state); + bool mod_zoom = Modifiers::Modifier::get(Modifiers::Type::CANVAS_ZOOM)->active(event->scroll.state); + bool mod_scroll_x = Modifiers::Modifier::get(Modifiers::Type::CANVAS_SCROLL_X)->active(event->scroll.state); + bool mod_scroll_y = Modifiers::Modifier::get(Modifiers::Type::CANVAS_SCROLL_Y)->active(event->scroll.state); + switch (event->type) { case GDK_2BUTTON_PRESS: if (panning) { @@ -370,7 +376,7 @@ bool ToolBase::root_handler(GdkEvent* event) { break; case 2: - if ((event->button.state & GDK_CONTROL_MASK) && !desktop->get_rotation_lock()) { + if (mod_rotate && !desktop->get_rotation_lock()) { // On screen canvas rotation preview // Grab background before doing anything else @@ -386,7 +392,7 @@ bool ToolBase::root_handler(GdkEvent* event) { Gdk::POINTER_MOTION_MASK, nullptr); // Cursor is null. - } else if (event->button.state & GDK_SHIFT_MASK) { + } else if (mod_zoom) { zoom_rb = 2; } else { // When starting panning, make sure there are no snap events pending because these might disable the panning again @@ -403,7 +409,7 @@ bool ToolBase::root_handler(GdkEvent* event) { break; case 3: - if ((event->button.state & GDK_SHIFT_MASK) || (event->button.state & GDK_CONTROL_MASK)) { + if (mod_scroll_x || mod_scroll_y) { // When starting panning, make sure there are no snap events pending because these might disable the panning again if (_uses_snap) { sp_event_context_discard_delayed_snap_event(this); @@ -524,8 +530,7 @@ bool ToolBase::root_handler(GdkEvent* event) { double const zoom_inc = prefs->getDoubleLimited( "/options/zoomincrement/value", M_SQRT2, 1.01, 10); - desktop->zoom_relative_keep_point(event_dt, (event->button.state - & GDK_SHIFT_MASK) ? 1 / zoom_inc : zoom_inc); + desktop->zoom_relative_keep_point(event_dt, zoom_inc); desktop->updateNow(); ret = TRUE; @@ -738,8 +743,6 @@ bool ToolBase::root_handler(GdkEvent* event) { break; case GDK_SCROLL: { - bool ctrl = (event->scroll.state & GDK_CONTROL_MASK); - bool shift = (event->scroll.state & GDK_SHIFT_MASK); int constexpr WHEEL_SCROLL_DEFAULT = 40; int const wheel_scroll = prefs->getIntLimited( @@ -749,8 +752,7 @@ bool ToolBase::root_handler(GdkEvent* event) { gdouble delta_x = 0; gdouble delta_y = 0; - if ((ctrl & shift) && !desktop->get_rotation_lock()) { - /* ctrl + shift, rotate */ + if (mod_rotate && !desktop->get_rotation_lock()) { double rotate_inc = prefs->getDoubleLimited( "/options/rotateincrement/value", 15, 1, 90, "°" ); @@ -786,7 +788,7 @@ bool ToolBase::root_handler(GdkEvent* event) { desktop->rotate_relative_keep_point(scroll_dt, rotate_inc); } - } else if (shift && !ctrl) { + } else if (mod_scroll_x || mod_scroll_y) { /* shift + wheel, pan left--right */ switch (event->scroll.direction) { @@ -814,7 +816,7 @@ bool ToolBase::root_handler(GdkEvent* event) { break; } - } else if (ctrl) { + } else if (mod_zoom) { /* ctrl + wheel, zoom in--out */ double rel_zoom; double const zoom_inc = prefs->getDoubleLimited( -- GitLab From 6320fa08d6951aff7625692fa55f27ddfe82ced8 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 16 Jul 2020 22:12:48 -0400 Subject: [PATCH 14/24] Improve view into preferences of modifiers --- src/ui/dialog/inkscape-preferences.cpp | 35 +++++++++++++------------- src/ui/modifiers.cpp | 20 +++++++++++++++ src/ui/modifiers.h | 5 ++++ 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 48eea74b66..7292f113ac 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -54,6 +54,7 @@ #include "svg/svg-color.h" +#include "ui/modifiers.h" #include "ui/interface.h" #include "ui/widget/style-swatch.h" @@ -2550,26 +2551,26 @@ void InkscapePreferences::onKBListKeyboardShortcuts() } // Tool mouse keys - Gtk::TreeStore::iterator iter_modifers = _kb_store->append(); - (*iter_modifers)[_kb_columns.name] = _("Modifiers"); - (*iter_modifers)[_kb_columns.shortcut] = ""; - (*iter_modifers)[_kb_columns.id] = ""; - (*iter_modifers)[_kb_columns.description] = ""; - (*iter_modifers)[_kb_columns.shortcutid] = 0; - (*iter_modifers)[_kb_columns.user_set] = 0; + Gtk::TreeStore::iterator iter_modifiers = _kb_store->append(); + (*iter_modifiers)[_kb_columns.name] = _("Modifiers"); + (*iter_modifiers)[_kb_columns.shortcut] = ""; + (*iter_modifiers)[_kb_columns.id] = ""; + (*iter_modifiers)[_kb_columns.description] = ""; + (*iter_modifiers)[_kb_columns.shortcutid] = 0; + (*iter_modifiers)[_kb_columns.user_set] = 0; - /*for(auto modifier: Modifier::getList()) { + for(auto modifier: Inkscape::Modifiers::Modifier::getList()) { // TODO: generate shortcut label and shortcut id etc - Gtk::TreeStore::iterator iter_modifer = _kb_store->append(); - (*iter_modifer)[_kb_columns.name] = modifier->get_name(); - (*iter_modifer)[_kb_columns.shortcut] = ""; - (*iter_modifer)[_kb_columns.id] = modifier->get_id(); - (*iter_modifer)[_kb_columns.description] = modifier->get_description(); - (*iter_modifer)[_kb_columns.shortcutid] = 0; - (*iter_modifer)[_kb_columns.user_set] = modifier->is_user_set(); - - }*/ + Gtk::TreeStore::iterator iter_modifier = _kb_store->append(iter_modifiers->children()); + (*iter_modifier)[_kb_columns.name] = modifier->get_name(); + (*iter_modifier)[_kb_columns.shortcut] = modifier->get_label(); + (*iter_modifier)[_kb_columns.id] = modifier->get_id(); + (*iter_modifier)[_kb_columns.description] = modifier->get_description(); + (*iter_modifier)[_kb_columns.shortcutid] = 0; + (*iter_modifier)[_kb_columns.user_set] = modifier->is_set(); + + } // re-order once after updating (then disable ordering again to increase performance) _kb_store->set_sort_column (_kb_columns.id, Gtk::SORT_ASCENDING ); diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 393c31f890..9dafed51b3 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -79,6 +79,26 @@ bool Modifier::active(int button_state) return get_and_mask() & button_state; } +/** + * Generate a label for any modifier keys based on the mask + * + * @param mask - The Modifier Mask such as {SHIFT & CTRL} + * @return a string of the keys needed for this mask to be true. + */ +char * generate_label(KeyMask mask) +{ + bool ctrl = mask & CTRL; + bool shift = mask & SHIFT; + bool alt = mask & ALT; + + gchar *label = g_strdup_printf("%s%s%s%s%s", + (ctrl ? "Ctrl" : ""), (ctrl && (shift || alt) ? "+" : ""), + (shift ? "Shift" : ""), (shift && alt ? "+ " : ""), + (alt ? "Alt" : "")); + + return label; +} + } // namespace Modifiers } // namespace Inkscape diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index f0ba35d28c..d42e0af0d7 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -31,6 +31,9 @@ enum Key : KeyMask { enum Triggers : Trigger {CLICK, DRAG, SCROLL, HANDLE}; // TODO: We may want to further define the tool, from ANY, SELECT, NODE etc. +// Generate a label such as Shift+Ctrl from any KeyMask +char * generate_label(KeyMask); + /** * This anonymous enum is used to provide a list of the Shifts */ @@ -111,6 +114,8 @@ public: } return _and_mask_default; } + // Generate labels such as "Shift+Ctrl" for the active modifier + char * get_label() { return generate_label(get_and_mask()); } /** * Inititalizes the Modifier with the parameters. -- GitLab From 1d5d52f1f0bbd2f092fa02015cb0fe3485103a4b Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Fri, 17 Jul 2020 07:08:00 -0400 Subject: [PATCH 15/24] Fix minor issue in header --- src/ui/modifiers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index d42e0af0d7..2e13794e12 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -32,7 +32,7 @@ enum Triggers : Trigger {CLICK, DRAG, SCROLL, HANDLE}; // TODO: We may want to further define the tool, from ANY, SELECT, NODE etc. // Generate a label such as Shift+Ctrl from any KeyMask -char * generate_label(KeyMask); +char * generate_label(KeyMask mask); /** * This anonymous enum is used to provide a list of the Shifts -- GitLab From 86d86dce862b7022607eea43aaca10c6a70d0314 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sun, 26 Jul 2020 23:20:30 -0400 Subject: [PATCH 16/24] Revert changes to the preferences dialog --- src/ui/dialog/inkscape-preferences.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 7292f113ac..02d097bac1 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -54,7 +54,6 @@ #include "svg/svg-color.h" -#include "ui/modifiers.h" #include "ui/interface.h" #include "ui/widget/style-swatch.h" @@ -2550,28 +2549,6 @@ void InkscapePreferences::onKBListKeyboardShortcuts() } } - // Tool mouse keys - Gtk::TreeStore::iterator iter_modifiers = _kb_store->append(); - (*iter_modifiers)[_kb_columns.name] = _("Modifiers"); - (*iter_modifiers)[_kb_columns.shortcut] = ""; - (*iter_modifiers)[_kb_columns.id] = ""; - (*iter_modifiers)[_kb_columns.description] = ""; - (*iter_modifiers)[_kb_columns.shortcutid] = 0; - (*iter_modifiers)[_kb_columns.user_set] = 0; - - for(auto modifier: Inkscape::Modifiers::Modifier::getList()) { - - // TODO: generate shortcut label and shortcut id etc - Gtk::TreeStore::iterator iter_modifier = _kb_store->append(iter_modifiers->children()); - (*iter_modifier)[_kb_columns.name] = modifier->get_name(); - (*iter_modifier)[_kb_columns.shortcut] = modifier->get_label(); - (*iter_modifier)[_kb_columns.id] = modifier->get_id(); - (*iter_modifier)[_kb_columns.description] = modifier->get_description(); - (*iter_modifier)[_kb_columns.shortcutid] = 0; - (*iter_modifier)[_kb_columns.user_set] = modifier->is_set(); - - } - // re-order once after updating (then disable ordering again to increase performance) _kb_store->set_sort_column (_kb_columns.id, Gtk::SORT_ASCENDING ); _kb_store->set_sort_column ( GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, Gtk::SORT_ASCENDING ); -- GitLab From 3338f8647ca1521cb8f13b4124f6c515a186c587 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Mon, 27 Jul 2020 00:06:46 -0400 Subject: [PATCH 17/24] Change char to std::string as advised --- src/ui/modifiers.cpp | 14 +++++++------- src/ui/modifiers.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 9dafed51b3..7ff3719a3f 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -85,18 +85,18 @@ bool Modifier::active(int button_state) * @param mask - The Modifier Mask such as {SHIFT & CTRL} * @return a string of the keys needed for this mask to be true. */ -char * generate_label(KeyMask mask) +std::string generate_label(KeyMask mask) { bool ctrl = mask & CTRL; bool shift = mask & SHIFT; bool alt = mask & ALT; - gchar *label = g_strdup_printf("%s%s%s%s%s", - (ctrl ? "Ctrl" : ""), (ctrl && (shift || alt) ? "+" : ""), - (shift ? "Shift" : ""), (shift && alt ? "+ " : ""), - (alt ? "Alt" : "")); - - return label; + return std::string() + .append(ctrl ? "Ctrl" : "") + .append(ctrl && (shift || alt) ? "+" : "") + .append(shift ? "Shift" : "") + .append(shift && alt ? "+ " : "") + .append(alt ? "Alt" : ""); } } // namespace Modifiers diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 2e13794e12..77d4f2656d 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -32,7 +32,7 @@ enum Triggers : Trigger {CLICK, DRAG, SCROLL, HANDLE}; // TODO: We may want to further define the tool, from ANY, SELECT, NODE etc. // Generate a label such as Shift+Ctrl from any KeyMask -char * generate_label(KeyMask mask); +std::string generate_label(KeyMask mask); /** * This anonymous enum is used to provide a list of the Shifts @@ -115,7 +115,7 @@ public: return _and_mask_default; } // Generate labels such as "Shift+Ctrl" for the active modifier - char * get_label() { return generate_label(get_and_mask()); } + std::string get_label() { return generate_label(get_and_mask()); } /** * Inititalizes the Modifier with the parameters. -- GitLab From 7d60d3e5b076087cf94aee91f586e94f28b51653 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Fri, 7 Aug 2020 03:58:30 -0400 Subject: [PATCH 18/24] Add xml parsing to get user defined modifier keys. --- src/shortcuts.cpp | 131 +++++++++++++++++++++++++++++---------------- src/shortcuts.h | 1 + src/ui/modifiers.h | 2 + 3 files changed, 88 insertions(+), 46 deletions(-) diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index e801b9bb4f..6d40e68691 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -49,14 +49,16 @@ #include "xml/repr.h" #include "document.h" #include "preferences.h" -#include "ui/tools/tool-base.h" #include "inkscape.h" #include "desktop.h" #include "path-prefix.h" +#include "ui/modifiers.h" +#include "ui/tools/tool-base.h" #include "ui/dialog/filedialog.h" using namespace Inkscape; using namespace Inkscape::IO::Resource; +using namespace Inkscape::Modifiers; static bool try_shortcuts_file(char const *filename, bool const is_user_set=false); static void read_shortcuts_file(char const *filename, bool const is_user_set=false); @@ -684,54 +686,38 @@ static void _read_shortcuts_file(XML::Node const *root, bool const is_user_set) continue; } - guint modifiers=0; + guint modifiers = parse_modifier_string(iter->attribute("modifiers"), verb_name); + sp_shortcut_set(keyval | modifiers, verb, is_primary, is_user_set); - gchar const *modifiers_string=iter->attribute("modifiers"); - if (modifiers_string) { - gchar const *iter=modifiers_string; - while (*iter) { - size_t length=strcspn(iter, ","); - gchar *mod=g_strndup(iter, length); - if (!strcmp(mod, "Control") || !strcmp(mod, "Ctrl")) { - modifiers |= SP_SHORTCUT_CONTROL_MASK; - } else if (!strcmp(mod, "Shift")) { - modifiers |= SP_SHORTCUT_SHIFT_MASK; - } else if (!strcmp(mod, "Alt")) { - modifiers |= SP_SHORTCUT_ALT_MASK; - } else if (!strcmp(mod, "Super")) { - modifiers |= SP_SHORTCUT_SUPER_MASK; - } else if (!strcmp(mod, "Hyper") || !strcmp(mod, "Cmd")) { - modifiers |= SP_SHORTCUT_HYPER_MASK; - } else if (!strcmp(mod, "Meta")) { - modifiers |= SP_SHORTCUT_META_MASK; - } else if (!strcmp(mod, "Primary")) { - auto display = Gdk::Display::get_default(); - if (display) { - GdkKeymap* keymap = display->get_keymap(); - GdkModifierType mod = - gdk_keymap_get_modifier_mask (keymap, GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR); - gdk_keymap_add_virtual_modifiers(keymap, &mod); - if (mod & GDK_CONTROL_MASK) - modifiers |= SP_SHORTCUT_CONTROL_MASK; - else if (mod & GDK_META_MASK) - modifiers |= SP_SHORTCUT_META_MASK; - else { - g_warning("unsupported primary accelerator "); - modifiers |= SP_SHORTCUT_CONTROL_MASK; - } - } else { - modifiers |= SP_SHORTCUT_CONTROL_MASK; - } - } else { - g_warning("Unknown modifier %s for %s", mod, verb_name); - } - g_free(mod); - iter += length; - if (*iter) iter++; - } + } else if (!strcmp(iter->name(), "modifier")) { + gchar const *mod_name = iter->attribute("action"); + if (!mod_name) { + g_warning("Missing modifier name (action= attribute) for shortcut"); + continue; + } + Modifier *mod = Modifier::get(mod_name); + if(mod == nullptr) { + g_warning("Can't find modifier '%s'", mod_name); + continue; } - sp_shortcut_set(keyval | modifiers, verb, is_primary, is_user_set); + // If mods isn't specified then it should use default, if it's an empty string + // then the modifier is None (i.e. happens all the time without a modifier) + gchar const *mod_attr = iter->attribute("modifiers"); + if(!mod_attr) continue; // Default, do nothing and no warning + guint sp_mods = parse_modifier_string(mod_attr, mod_name); + + // Convert SP_SHORTCUT modifiers to KeyMask + KeyMask user_modifier = 0; + if(sp_mods & SP_SHORTCUT_CONTROL_MASK) user_modifier |= CTRL; + if(sp_mods & SP_SHORTCUT_SHIFT_MASK) user_modifier |= SHIFT; + if(sp_mods & SP_SHORTCUT_ALT_MASK) user_modifier |= ALT; + if(sp_mods & SP_SHORTCUT_SUPER_MASK) user_modifier |= SUPER; + if(sp_mods & SP_SHORTCUT_HYPER_MASK) user_modifier |= HYPER; + if(sp_mods & SP_SHORTCUT_META_MASK) user_modifier |= META; + + g_warning("Setting '%s' to '%s' (user defined modifier)", mod_name, mod_attr); + mod->set(user_modifier); } else if (!strcmp(iter->name(), "keys")) { // include another keys file @@ -740,6 +726,59 @@ static void _read_shortcuts_file(XML::Node const *root, bool const is_user_set) } } +/** + * Parse the modifier string out of the keys xml attribute + */ +guint +parse_modifier_string(gchar const *modifiers_string, gchar const *verb_name) +{ + guint modifiers = 0; + if (modifiers_string) { + gchar const *iter=modifiers_string; + while (*iter) { + size_t length=strcspn(iter, ","); + gchar *mod=g_strndup(iter, length); + if (!strcmp(mod, "Control") || !strcmp(mod, "Ctrl")) { + modifiers |= SP_SHORTCUT_CONTROL_MASK; + } else if (!strcmp(mod, "Shift")) { + modifiers |= SP_SHORTCUT_SHIFT_MASK; + } else if (!strcmp(mod, "Alt")) { + modifiers |= SP_SHORTCUT_ALT_MASK; + } else if (!strcmp(mod, "Super")) { + modifiers |= SP_SHORTCUT_SUPER_MASK; + } else if (!strcmp(mod, "Hyper") || !strcmp(mod, "Cmd")) { + modifiers |= SP_SHORTCUT_HYPER_MASK; + } else if (!strcmp(mod, "Meta")) { + modifiers |= SP_SHORTCUT_META_MASK; + } else if (!strcmp(mod, "Primary")) { + auto display = Gdk::Display::get_default(); + if (display) { + GdkKeymap* keymap = display->get_keymap(); + GdkModifierType mod = + gdk_keymap_get_modifier_mask (keymap, GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR); + gdk_keymap_add_virtual_modifiers(keymap, &mod); + if (mod & GDK_CONTROL_MASK) + modifiers |= SP_SHORTCUT_CONTROL_MASK; + else if (mod & GDK_META_MASK) + modifiers |= SP_SHORTCUT_META_MASK; + else { + g_warning("unsupported primary accelerator "); + modifiers |= SP_SHORTCUT_CONTROL_MASK; + } + } else { + modifiers |= SP_SHORTCUT_CONTROL_MASK; + } + } else { + g_warning("Unknown modifier %s for %s", mod, verb_name); + } + g_free(mod); + iter += length; + if (*iter) iter++; + } + } + return modifiers; +} + /** * Removes a keyboard shortcut for the given verb. * (Removes any existing binding for the given shortcut, including appropriately diff --git a/src/shortcuts.h b/src/shortcuts.h index ab41be8b83..76f16c1ab3 100644 --- a/src/shortcuts.h +++ b/src/shortcuts.h @@ -71,6 +71,7 @@ void sp_shortcut_file_import_do(char const *importname); void sp_shortcut_file_export_do(char const *exportname); GtkAccelGroup *sp_shortcut_get_accel_group(); void sp_shortcut_add_accelerator(GtkWidget *item, unsigned int const shortcut); +guint parse_modifier_string(gchar const *modifiers_string, gchar const *verb_name); #endif diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 77d4f2656d..523bb6c2a1 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -26,6 +26,8 @@ enum Key : KeyMask { CTRL = GDK_CONTROL_MASK, ALT = GDK_MOD1_MASK, SUPER = GDK_SUPER_MASK, + HYPER = GDK_HYPER_MASK, + META = GDK_META_MASK, }; // Triggers used for collision warnings, two tools are using the same trigger enum Triggers : Trigger {CLICK, DRAG, SCROLL, HANDLE}; -- GitLab From 5183c3b6b8cf82b5244cca40413d0919580f48b6 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Fri, 7 Aug 2020 04:45:24 -0400 Subject: [PATCH 19/24] Remove Scale from center and use the axis and ratio confines --- src/seltrans.cpp | 19 +++++++++++-------- src/ui/modifiers.cpp | 11 +++++------ src/ui/modifiers.h | 3 +-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 7e09e1d191..da26d6e703 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -49,6 +49,7 @@ #include "object/sp-namedview.h" #include "object/sp-root.h" +#include "ui/modifiers.h" #include "ui/tools/select-tool.h" using Inkscape::DocumentUndo; @@ -791,7 +792,8 @@ gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, Geom::Point *position, // When holding shift while rotating or skewing, the transformation will be // relative to the point opposite of the handle; otherwise it will be relative // to the center as set for the selection - if ((!(state & GDK_SHIFT_MASK) == !(_state == STATE_ROTATE)) && (handle.type != HANDLE_CENTER)) { + auto off_center = Modifiers::Modifier::get(Modifiers::Type::TRANS_OFF_CENTER)->active(state); + if ((!off_center == !(_state == STATE_ROTATE)) && (handle.type != HANDLE_CENTER)) { _origin = _opposite; _origin_for_bboxpoints = _opposite_for_bboxpoints; _origin_for_specpoints = _opposite_for_specpoints; @@ -898,7 +900,8 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state) // In all other cases we should try to snap now Inkscape::PureScale *bb, *sn; - if ((state & GDK_CONTROL_MASK) || _desktop->isToolboxButtonActive ("lock")) { + auto ratio_confine = Modifiers::Modifier::get(Modifiers::Type::MOVE_RATIO_CONFINE)->active(state); + if (ratio_confine || _desktop->isToolboxButtonActive ("lock")) { // Scale is locked to a 1:1 aspect ratio, so that s[X] must be made to equal s[Y]. // // The aspect-ratio must be locked before snapping @@ -1293,7 +1296,7 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state) m.setup(_desktop); m.setRotationCenterSource(items); - if (state & GDK_CONTROL_MASK) { // with Ctrl, constrain to axes + if (Modifiers::Modifier::get(Modifiers::Type::MOVE_AXIS_CONFINE)->active(state)) { std::vector constraints; constraints.emplace_back(_point, Geom::Point(1, 0)); constraints.emplace_back(_point, Geom::Point(0, 1)); @@ -1379,10 +1382,10 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) Geom::Point dxy = xy - _point; bool const alt = (state & GDK_MOD1_MASK); - bool const control = (state & GDK_CONTROL_MASK); bool const shift = (state & GDK_SHIFT_MASK); + auto axis_confine = Modifiers::Modifier::get(Modifiers::Type::MOVE_AXIS_CONFINE)->active(state); - if (control) { // constrained to the orthogonal axes + if (axis_confine) { if (fabs(dxy[Geom::X]) > fabs(dxy[Geom::Y])) { dxy[Geom::Y] = 0; } else { @@ -1407,7 +1410,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) Inkscape::PureTranslate *bb, *sn; - if (control) { // constrained movement with snapping + if (axis_confine) { // constrained movement with snapping /* Snap to things, and also constrain to horizontal or vertical movement */ @@ -1419,7 +1422,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) // individually for each point to be snapped; this will be handled however by snapTransformed() bb = new Inkscape::PureTranslateConstrained(dxy[dim], dim); sn = new Inkscape::PureTranslateConstrained(dxy[dim], dim); - } else { // !control + } else { /* Snap to things with no constraint */ bb = new Inkscape::PureTranslate(dxy); sn = new Inkscape::PureTranslate(dxy); @@ -1461,7 +1464,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) } else { // We didn't snap, so remove any previous snap indicator _desktop->snapindicator->remove_snaptarget(); - if (control) { + if (axis_confine) { // If we didn't snap, then we should still constrain horizontally or vertically // (When we did snap, then this constraint has already been enforced by // calling constrainedSnapTranslate() above) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 7ff3719a3f..4ccfae90a2 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -40,12 +40,11 @@ decltype(Modifier::_modifiers) Modifier::_modifiers { {Type::SELECT_CYCLE, new Modifier("select-cycle", "Cycle through objects", "Scroll through objects under the cursor.", ALT, SCROLL)}, // Transform handle modifiers (applies to multiple tools) - {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL, HANDLE)}, - {Type::SCALE_RATIO_CONFINE, new Modifier("scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL, HANDLE)}, - {Type::SCALE_FROM_CENTER, new Modifier("scale-from-center", "Scale from center", "When resizing obects, scale from the center", SHIFT, HANDLE)}, - {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT, HANDLE)}, - {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL, HANDLE)}, - {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "When rotating or skewing, use the far point as the anchor", SHIFT, HANDLE)}, + {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL, DRAG)}, // MOVE by DRAG + {Type::SCALE_RATIO_CONFINE, new Modifier("scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL, HANDLE)}, // SCALE + {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT, HANDLE)}, // seltrans.cpp:916+1027+1424 + {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL, HANDLE)}, // seltrans.cpp:1179+1268 + {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "When resizing, rotating or skewing, change the center point", SHIFT, HANDLE)}, // SCALE/ROTATE/SKEW }; /** diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index 523bb6c2a1..c0cce97dc6 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -60,10 +60,9 @@ enum class Type { // Transform handles (applies to multiple tools) MOVE_AXIS_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} SCALE_RATIO_CONFINE, // Confine resize aspect ratio {HANDLE+CTRL} - SCALE_FROM_CENTER, // Resize from center {HANDLE+SHIFT} SCALE_FIXED_RATIO, // Resize by fixed ratio sizes {HANDLE+ALT} TRANS_FIXED_RATIO, // Rotate/skew by fixed ratio angles {HANDLE+CTRL} - TRANS_OFF_CENTER, // Rotate/skew from oposite corner {HANDLE+SHIFT} + TRANS_OFF_CENTER, // Scale/Rotate/skew from oposite corner {HANDLE+SHIFT} // TODO: Alignment ommitted because it's UX is not completed }; -- GitLab From 536f6876a50eb75756651b3272af5dac8c17b398 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sat, 8 Aug 2020 05:09:36 -0400 Subject: [PATCH 20/24] Complete sample modifiers and add defaults to inkscape.xml keys file --- share/keys/inkscape.xml | 20 +++++++++++++++ src/seltrans.cpp | 55 ++++++++++++++++++++++------------------- src/ui/modifiers.cpp | 14 +++++++---- src/ui/modifiers.h | 6 +++-- 4 files changed, 62 insertions(+), 33 deletions(-) diff --git a/share/keys/inkscape.xml b/share/keys/inkscape.xml index 3c82584d08..337bca3391 100644 --- a/share/keys/inkscape.xml +++ b/share/keys/inkscape.xml @@ -637,4 +637,24 @@ override) the bindings in the main default.xml. --> + + + + + + + + + + + + + + + + + + + + diff --git a/src/seltrans.cpp b/src/seltrans.cpp index da26d6e703..823a76348d 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -884,7 +884,8 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state) _absolute_affine = Geom::identity(); //Initialize the scaler - if (state & GDK_MOD1_MASK) { // scale by an integer multiplier/divider + auto fixed_ratio = Modifiers::Modifier::get(Modifiers::Type::SCALE_FIXED_RATIO)->active(state); + if (fixed_ratio) { // scale by an integer multiplier/divider // We're scaling either the visual or the geometric bbox here (see the comment above) for ( unsigned int i = 0 ; i < 2 ; i++ ) { if (fabs(default_scale[i]) > 1) { @@ -900,8 +901,8 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state) // In all other cases we should try to snap now Inkscape::PureScale *bb, *sn; - auto ratio_confine = Modifiers::Modifier::get(Modifiers::Type::MOVE_RATIO_CONFINE)->active(state); - if (ratio_confine || _desktop->isToolboxButtonActive ("lock")) { + auto confine = Modifiers::Modifier::get(Modifiers::Type::SCALE_CONFINE)->active(state); + if (confine || _desktop->isToolboxButtonActive ("lock")) { // Scale is locked to a 1:1 aspect ratio, so that s[X] must be made to equal s[Y]. // // The aspect-ratio must be locked before snapping @@ -996,7 +997,8 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom _absolute_affine = Geom::identity(); //Initialize the scaler - if (state & GDK_MOD1_MASK) { // stretch by an integer multiplier/divider + auto fixed_ratio = Modifiers::Modifier::get(Modifiers::Type::SCALE_FIXED_RATIO)->active(state); + if (fixed_ratio) { // stretch by an integer multiplier/divider if (fabs(default_scale[axis]) > 1) { default_scale[axis] = round(default_scale[axis]); } else if (default_scale[axis] != 0) { @@ -1011,10 +1013,9 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom SnapManager &m = _desktop->namedview->snap_manager; m.setup(_desktop, false, _items_const); - bool symmetrical = state & GDK_CONTROL_MASK; - - Inkscape::PureStretchConstrained bb = Inkscape::PureStretchConstrained(Geom::Coord(default_scale[axis]), _origin_for_bboxpoints, Geom::Dim2(axis), symmetrical); - Inkscape::PureStretchConstrained sn = Inkscape::PureStretchConstrained(Geom::Coord(geom_scale[axis]), _origin_for_specpoints, Geom::Dim2(axis), symmetrical); + auto confine = Modifiers::Modifier::get(Modifiers::Type::SCALE_CONFINE)->active(state); + Inkscape::PureStretchConstrained bb = Inkscape::PureStretchConstrained(Geom::Coord(default_scale[axis]), _origin_for_bboxpoints, Geom::Dim2(axis), confine); + Inkscape::PureStretchConstrained sn = Inkscape::PureStretchConstrained(Geom::Coord(geom_scale[axis]), _origin_for_specpoints, Geom::Dim2(axis), confine); m.snapTransformed(_bbox_points, _point, bb); m.snapTransformed(_snap_points, _point, sn); @@ -1029,8 +1030,8 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom geom_scale[axis] = sn.getMagnitude(); } - if (symmetrical) { - // on ctrl, apply symmetrical scaling instead of stretching + if (confine) { + // on scale_confine, apply symmetrical scaling instead of stretching // Preserve aspect ratio, but never flip in the dimension not being edited (by using fabs()) default_scale[perp] = fabs(default_scale[axis]); geom_scale[perp] = fabs(geom_scale[axis]); @@ -1148,7 +1149,8 @@ gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, Geom::P double radians = atan(skew[dim_a] / scale[dim_a]); - if (state & GDK_CONTROL_MASK) { + auto fixed_ratio = Modifiers::Modifier::get(Modifiers::Type::TRANS_FIXED_RATIO)->active(state); + if (fixed_ratio) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); // Snap to defined angle increments int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); @@ -1237,7 +1239,8 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state) Geom::Rotate r2(q2); double radians = atan2(Geom::dot(Geom::rot90(d1), d2), Geom::dot(d1, d2));; - if (state & GDK_CONTROL_MASK) { + auto fixed_ratio = Modifiers::Modifier::get(Modifiers::Type::TRANS_FIXED_RATIO)->active(state); + if (fixed_ratio) { // Snap to defined angle increments double cos_t = Geom::dot(q1, q2); double sin_t = Geom::dot(Geom::rot90(q1), q2); @@ -1296,17 +1299,17 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state) m.setup(_desktop); m.setRotationCenterSource(items); - if (Modifiers::Modifier::get(Modifiers::Type::MOVE_AXIS_CONFINE)->active(state)) { + auto no_snap = Modifiers::Modifier::get(Modifiers::Type::TRANS_SNAPPING)->active(state); + auto confine = Modifiers::Modifier::get(Modifiers::Type::MOVE_CONFINE)->active(state); + if (confine) { std::vector constraints; constraints.emplace_back(_point, Geom::Point(1, 0)); constraints.emplace_back(_point, Geom::Point(0, 1)); - Inkscape::SnappedPoint sp = m.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER), constraints, state & GDK_SHIFT_MASK); + Inkscape::SnappedPoint sp = m.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER), constraints, no_snap); pt = sp.getPoint(); } - else { - if (!(state & GDK_SHIFT_MASK)) { // Shift disables snapping - m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER); - } + else if (!no_snap) { + m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER); } m.unSetup(); @@ -1381,11 +1384,11 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) /* The amount that we've moved by during this drag */ Geom::Point dxy = xy - _point; - bool const alt = (state & GDK_MOD1_MASK); - bool const shift = (state & GDK_SHIFT_MASK); - auto axis_confine = Modifiers::Modifier::get(Modifiers::Type::MOVE_AXIS_CONFINE)->active(state); + auto fixed_ratio = Modifiers::Modifier::get(Modifiers::Type::MOVE_FIXED_RATIO)->active(state); + auto no_snap = Modifiers::Modifier::get(Modifiers::Type::TRANS_SNAPPING)->active(state); + auto confine = Modifiers::Modifier::get(Modifiers::Type::MOVE_CONFINE)->active(state); - if (axis_confine) { + if (confine) { if (fabs(dxy[Geom::X]) > fabs(dxy[Geom::Y])) { dxy[Geom::Y] = 0; } else { @@ -1393,11 +1396,11 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) } } - if (alt) {// Alt pressed means: move only by integer multiples of the grid spacing + if (fixed_ratio) {// Alt pressed means: move only by integer multiples of the grid spacing m.setup(_desktop, true, _items_const); dxy = m.multipleOfGridPitch(dxy, _point); m.unSetup(); - } else if (!shift) { //!shift: with snapping + } else if (!no_snap) { /* We're snapping to things, possibly with a constraint to horizontal or ** vertical movement. Obtain a list of possible translations and then ** pick the smallest. @@ -1410,7 +1413,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) Inkscape::PureTranslate *bb, *sn; - if (axis_confine) { // constrained movement with snapping + if (confine) { // constrained movement with snapping /* Snap to things, and also constrain to horizontal or vertical movement */ @@ -1464,7 +1467,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) } else { // We didn't snap, so remove any previous snap indicator _desktop->snapindicator->remove_snaptarget(); - if (axis_confine) { + if (confine) { // If we didn't snap, then we should still constrain horizontally or vertically // (When we did snap, then this constraint has already been enforced by // calling constrainedSnapTranslate() above) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 4ccfae90a2..24fa787227 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -40,11 +40,15 @@ decltype(Modifier::_modifiers) Modifier::_modifiers { {Type::SELECT_CYCLE, new Modifier("select-cycle", "Cycle through objects", "Scroll through objects under the cursor.", ALT, SCROLL)}, // Transform handle modifiers (applies to multiple tools) - {Type::MOVE_AXIS_CONFINE, new Modifier("move-confine", "Move confine", "When dragging items, confine to either x or y axis", CTRL, DRAG)}, // MOVE by DRAG - {Type::SCALE_RATIO_CONFINE, new Modifier("scale-confine", "Scale confine", "When resizing objects, confine the aspect ratio", CTRL, HANDLE)}, // SCALE - {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When resizing objects, scale by fixed amounts", ALT, HANDLE)}, // seltrans.cpp:916+1027+1424 - {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL, HANDLE)}, // seltrans.cpp:1179+1268 - {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "When resizing, rotating or skewing, change the center point", SHIFT, HANDLE)}, // SCALE/ROTATE/SKEW + {Type::MOVE_CONFINE, new Modifier("move-confine", "Move one axis only", "When dragging items, confine to either x or y axis.", CTRL, DRAG)}, // MOVE by DRAG + {Type::MOVE_FIXED_RATIO, new Modifier("move-fixed-ratio", "Move fixed amounts", "Move the objects by fixed amounts when dragging.", ALT, DRAG)}, // MOVE by DRAG + {Type::SCALE_CONFINE, new Modifier("scale-confine", "Keep aspect ratio", "When resizing objects, confine the aspect ratio.", CTRL, HANDLE)}, // SCALE/STRETCH + {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When moving or resizing objects, use fixed amounts.", ALT, HANDLE)}, // SCALE/STRETCH + {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL, HANDLE)}, // ROTATE/SKEW + {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "Change the center point when transforming objects.", SHIFT, HANDLE)}, // SCALE/ROTATE/SKEW + {Type::TRANS_SNAPPING, new Modifier("trans-snapping", "Disable Snapping", "Disable snapping when transforming objects.", SHIFT, DRAG)}, // MOVE/SCALE/STRETCH/ROTATE/SKEW + // Center handle click: seltrans.cpp:734 SHIFT + // Align handle click: seltrans.cpp:1365 SHIFT }; /** diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index c0cce97dc6..a44133dc12 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -58,11 +58,13 @@ enum class Type { SELECT_CYCLE, // Cycle through objects under cursor {ALT+SCROLL} // Transform handles (applies to multiple tools) - MOVE_AXIS_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} - SCALE_RATIO_CONFINE, // Confine resize aspect ratio {HANDLE+CTRL} + MOVE_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL} + MOVE_FIXED_RATIO, // Move objects by fixed amounts {HANDLE+ALT} + SCALE_CONFINE, // Confine resize aspect ratio {HANDLE+CTRL} SCALE_FIXED_RATIO, // Resize by fixed ratio sizes {HANDLE+ALT} TRANS_FIXED_RATIO, // Rotate/skew by fixed ratio angles {HANDLE+CTRL} TRANS_OFF_CENTER, // Scale/Rotate/skew from oposite corner {HANDLE+SHIFT} + TRANS_SNAPPING, // Disable snapping while transforming {HANDLE+SHIFT} // TODO: Alignment ommitted because it's UX is not completed }; -- GitLab From b95fdd9888e675f7176a59a1d6a77200180f7dee Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sat, 8 Aug 2020 05:12:23 -0400 Subject: [PATCH 21/24] Remove debug print from shortcuts --- src/shortcuts.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index 6d40e68691..66e356f91f 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -716,7 +716,6 @@ static void _read_shortcuts_file(XML::Node const *root, bool const is_user_set) if(sp_mods & SP_SHORTCUT_HYPER_MASK) user_modifier |= HYPER; if(sp_mods & SP_SHORTCUT_META_MASK) user_modifier |= META; - g_warning("Setting '%s' to '%s' (user defined modifier)", mod_name, mod_attr); mod->set(user_modifier); } else if (!strcmp(iter->name(), "keys")) { -- GitLab From 12f9f28d39327d01f499203ae1e8f11bc44a367f Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Mon, 10 Aug 2020 11:09:09 -0400 Subject: [PATCH 22/24] Start work on updating the tooltip texts with the selected modifiers --- src/shortcuts.cpp | 13 ++++++++++--- src/shortcuts.h | 1 + src/ui/modifiers.cpp | 35 +++++++++++++++++++++++----------- src/ui/tools/select-tool.cpp | 13 ++++++++++--- src/widgets/desktop-widget.cpp | 4 ++++ 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index 66e356f91f..27dbe3e733 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -140,6 +140,13 @@ void sp_shortcut_init() try_shortcuts_file(get_path(USER, KEYS, "default.xml"), true); } +/* + * Loads the keys file if required, but not if verbs already exist. + */ +void sp_shortcut_ensure_init() { + if (!verbs) sp_shortcut_init(); +} + static bool try_shortcuts_file(char const *filename, bool const is_user_set) { using Inkscape::IO::file_test; @@ -786,7 +793,7 @@ parse_modifier_string(gchar const *modifiers_string, gchar const *verb_name) void sp_shortcut_unset(unsigned int const shortcut) { - if (!verbs) sp_shortcut_init(); + sp_shortcut_ensure_init(); Inkscape::Verb *verb = (*verbs)[shortcut]; @@ -870,7 +877,7 @@ sp_shortcut_get_modifiers(unsigned int const shortcut) void sp_shortcut_set(unsigned int const shortcut, Inkscape::Verb *const verb, bool const is_primary, bool const is_user_set) { - if (!verbs) sp_shortcut_init(); + sp_shortcut_ensure_init(); Inkscape::Verb *old_verb = (*verbs)[shortcut]; (*verbs)[shortcut] = verb; @@ -894,7 +901,7 @@ sp_shortcut_set(unsigned int const shortcut, Inkscape::Verb *const verb, bool co Inkscape::Verb * sp_shortcut_get_verb(unsigned int shortcut) { - if (!verbs) sp_shortcut_init(); + sp_shortcut_ensure_init(); return (*verbs)[shortcut]; } diff --git a/src/shortcuts.h b/src/shortcuts.h index 76f16c1ab3..279ad16af8 100644 --- a/src/shortcuts.h +++ b/src/shortcuts.h @@ -51,6 +51,7 @@ namespace Inkscape { bool sp_shortcut_invoke (unsigned int shortcut, Inkscape::UI::View::View *view); void sp_shortcut_init(); +void sp_shortcut_ensure_init(); Inkscape::Verb * sp_shortcut_get_verb (unsigned int shortcut); unsigned int sp_shortcut_get_primary (Inkscape::Verb * verb); // Returns GDK_VoidSymbol if no shortcut is found. char* sp_shortcut_get_label (unsigned int shortcut); // Returns the human readable form of the shortcut (or NULL), for example Shift+Ctrl+F. Free the returned string with g_free. diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 24fa787227..77b3c5d0f9 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -28,7 +28,7 @@ decltype(Modifier::_modifiers) Modifier::_modifiers { {Type::CANVAS_SCROLL_Y, new Modifier("canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0, SCROLL)}, {Type::CANVAS_SCROLL_X, new Modifier("canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT, SCROLL)}, {Type::CANVAS_ZOOM, new Modifier("canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL, SCROLL)}, - {Type::CANVAS_ROTATE, new Modifier("canvs-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL, SCROLL)}, + {Type::CANVAS_ROTATE, new Modifier("canvas-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL, SCROLL)}, // Select tool modifiers (minus transforms) {Type::SELECT_ADD_TO, new Modifier("select-add-to", "Add to selection", "Add items to existing selection", SHIFT, CLICK)}, @@ -90,16 +90,29 @@ bool Modifier::active(int button_state) */ std::string generate_label(KeyMask mask) { - bool ctrl = mask & CTRL; - bool shift = mask & SHIFT; - bool alt = mask & ALT; - - return std::string() - .append(ctrl ? "Ctrl" : "") - .append(ctrl && (shift || alt) ? "+" : "") - .append(shift ? "Shift" : "") - .append(shift && alt ? "+ " : "") - .append(alt ? "Alt" : ""); + auto ret = std::string(); + if(mask & CTRL) ret.append("Ctrl"); + if(mask & SHIFT) { + if(!ret.empty()) ret.append("+"); + ret.append("Shift"); + } + if(mask & ALT) { + if(!ret.empty()) ret.append("+"); + ret.append("Alt"); + } + if(mask & SUPER) { + if(!ret.empty()) ret.append("+"); + ret.append("Super"); + } + if(mask & HYPER) { + if(!ret.empty()) ret.append("+"); + ret.append("Hyper"); + } + if(mask & META) { + if(!ret.empty()) ret.append("+"); + ret.append("Meta"); + } + return ret; } } // namespace Modifiers diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 2e5394af8d..5efbaa3999 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -159,12 +159,19 @@ SelectTool::~SelectTool() { void SelectTool::setup() { ToolBase::setup(); + auto select_click = Modifier::get(Modifiers::Type::SELECT_ADD_TO)->get_label(); + auto select_scroll = Modifier::get(Modifiers::Type::SELECT_CYCLE)->get_label(); + + auto no_selection_msg = g_strdup_printf( + _("No objects selected. Click, %s+click, %s+scroll mouse on top of objects, or drag around objects to select."), + select_click.c_str(), select_scroll.c_str()); + this->_describer = new Inkscape::SelectionDescriber( desktop->selection, desktop->messageStack(), - _("Click selection to toggle scale/rotation handles (or Shift+s)"), - _("No objects selected. Click, Shift+click, Alt+scroll mouse on top of objects, or drag around objects to select.") - ); + _("Click selection again to toggle scale/rotation handles."), + no_selection_msg); + free(no_selection_msg); // Is this right? this->_seltrans = new Inkscape::SelTrans(desktop); diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index d53f534a91..136416e417 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -38,6 +38,7 @@ #include "file.h" #include "inkscape-version.h" #include "verbs.h" +#include "shortcuts.h" #include "display/control/canvas-axonomgrid.h" #include "display/control/canvas-item-drawing.h" @@ -1418,6 +1419,9 @@ SPDesktopWidget::SPDesktopWidget(SPDocument *document) dtw->_ruler_origin = Geom::Point(0,0); //namedview->gridorigin; Why was the grid origin used here? + // Loading the shortcuts first will allow initial strings to be correct. + sp_shortcut_ensure_init(); + // This section seems backwards! dtw->desktop = new SPDesktop(); dtw->desktop->init (namedview, dtw->_canvas, this); -- GitLab From 2a1b387df434727e17a4bbb3f654f9da93c4ab50 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 13 Aug 2020 05:11:59 -0400 Subject: [PATCH 23/24] Make modifier names and desc translatable, fix tooltips --- src/ui/modifiers.cpp | 81 ++++++++++++++++++++++++++++-------- src/ui/modifiers.h | 11 +++-- src/ui/tools/select-tool.cpp | 17 ++++---- 3 files changed, 81 insertions(+), 28 deletions(-) diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index 77b3c5d0f9..afb02c8a3f 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -15,7 +15,9 @@ #include #include +#include #include "modifiers.h" +#include "ui/tools/tool-base.h" namespace Inkscape { namespace Modifiers { @@ -25,28 +27,28 @@ Modifier::Lookup Modifier::_modifier_lookup; // these must be in the same order as the * enum in "modifers.h" decltype(Modifier::_modifiers) Modifier::_modifiers { // Canvas modifiers - {Type::CANVAS_SCROLL_Y, new Modifier("canvas-scroll-y", "Vertical scroll", "Scroll up and down", 0, SCROLL)}, - {Type::CANVAS_SCROLL_X, new Modifier("canvas-scroll-x", "Horizontal scroll", "Scroll left and right", SHIFT, SCROLL)}, - {Type::CANVAS_ZOOM, new Modifier("canvas-zoom", "Canvas zoom", "Zoom in and out with scroll wheel", CTRL, SCROLL)}, - {Type::CANVAS_ROTATE, new Modifier("canvas-rotate", "Canavas rotate", "Rotate the canvas with scroll wheel", SHIFT & CTRL, SCROLL)}, + {Type::CANVAS_SCROLL_Y, new Modifier("canvas-scroll-y", _("Vertical scroll"), _("Scroll up and down"), 0, SCROLL)}, + {Type::CANVAS_SCROLL_X, new Modifier("canvas-scroll-x", _("Horizontal scroll"), _("Scroll left and right"), SHIFT, SCROLL)}, + {Type::CANVAS_ZOOM, new Modifier("canvas-zoom", _("Canvas zoom"), _("Zoom in and out with scroll wheel"), CTRL, SCROLL)}, + {Type::CANVAS_ROTATE, new Modifier("canvas-rotate", _("Canavas rotate"), _("Rotate the canvas with scroll wheel"), SHIFT & CTRL, SCROLL)}, // Select tool modifiers (minus transforms) - {Type::SELECT_ADD_TO, new Modifier("select-add-to", "Add to selection", "Add items to existing selection", SHIFT, CLICK)}, - {Type::SELECT_IN_GROUPS, new Modifier("select-in-groups", "Select inside groups", "Ignore groups when selecting items", CTRL, CLICK)}, - {Type::SELECT_TOUCH_PATH, new Modifier("select-touch-path", "Select with touch-path", "Draw a band around items to select them", ALT, DRAG)}, - {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", "Select with box", "Don't drag items, select more with a box", SHIFT, DRAG)}, - {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", "Select the first", "Drag the first item the mouse hits", CTRL, DRAG)}, - {Type::SELECT_FORCE_DRAG, new Modifier("select-force-drag", "Forced Drag", "Drag objects even if the mouse isn't over them.", ALT, DRAG)}, - {Type::SELECT_CYCLE, new Modifier("select-cycle", "Cycle through objects", "Scroll through objects under the cursor.", ALT, SCROLL)}, + {Type::SELECT_ADD_TO, new Modifier("select-add-to", _("Add to selection"), _("Add items to existing selection"), SHIFT, CLICK)}, + {Type::SELECT_IN_GROUPS, new Modifier("select-in-groups", _("Select inside groups"), _("Ignore groups when selecting items"), CTRL, CLICK)}, + {Type::SELECT_TOUCH_PATH, new Modifier("select-touch-path", _("Select with touch-path"), _("Draw a band around items to select them"), ALT, DRAG)}, + {Type::SELECT_ALWAYS_BOX, new Modifier("select-always-box", _("Select with box"), _("Don't drag items, select more with a box"), SHIFT, DRAG)}, + {Type::SELECT_FIRST_HIT, new Modifier("select-first-hit", _("Select the first"), _("Drag the first item the mouse hits"), CTRL, DRAG)}, + {Type::SELECT_FORCE_DRAG, new Modifier("select-force-drag", _("Forced Drag"), _("Drag objects even if the mouse isn't over them."), ALT, DRAG)}, + {Type::SELECT_CYCLE, new Modifier("select-cycle", _("Cycle through objects"), _("Scroll through objects under the cursor."), ALT, SCROLL)}, // Transform handle modifiers (applies to multiple tools) - {Type::MOVE_CONFINE, new Modifier("move-confine", "Move one axis only", "When dragging items, confine to either x or y axis.", CTRL, DRAG)}, // MOVE by DRAG - {Type::MOVE_FIXED_RATIO, new Modifier("move-fixed-ratio", "Move fixed amounts", "Move the objects by fixed amounts when dragging.", ALT, DRAG)}, // MOVE by DRAG - {Type::SCALE_CONFINE, new Modifier("scale-confine", "Keep aspect ratio", "When resizing objects, confine the aspect ratio.", CTRL, HANDLE)}, // SCALE/STRETCH - {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", "Scale fixed amounts", "When moving or resizing objects, use fixed amounts.", ALT, HANDLE)}, // SCALE/STRETCH - {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", "Transform in increments", "Rotate or skew by fixed amounts", CTRL, HANDLE)}, // ROTATE/SKEW - {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", "Transform against center", "Change the center point when transforming objects.", SHIFT, HANDLE)}, // SCALE/ROTATE/SKEW - {Type::TRANS_SNAPPING, new Modifier("trans-snapping", "Disable Snapping", "Disable snapping when transforming objects.", SHIFT, DRAG)}, // MOVE/SCALE/STRETCH/ROTATE/SKEW + {Type::MOVE_CONFINE, new Modifier("move-confine", _("Move one axis only"), _("When dragging items, confine to either x or y axis."), CTRL, DRAG)}, // MOVE by DRAG + {Type::MOVE_FIXED_RATIO, new Modifier("move-fixed-ratio", _("Move fixed amounts"), _("Move the objects by fixed amounts when dragging."), ALT, DRAG)}, // MOVE by DRAG + {Type::SCALE_CONFINE, new Modifier("scale-confine", _("Keep aspect ratio"), _("When resizing objects, confine the aspect ratio."), CTRL, HANDLE)}, // SCALE/STRETCH + {Type::SCALE_FIXED_RATIO, new Modifier("scale-fixed-ratio", _("Scale fixed amounts"), _("When moving or resizing objects, use fixed amounts."), ALT, HANDLE)}, // SCALE/STRETCH + {Type::TRANS_FIXED_RATIO, new Modifier("trans-fixed-ratio", _("Transform in increments"), _("Rotate or skew by fixed amounts"), CTRL, HANDLE)}, // ROTATE/SKEW + {Type::TRANS_OFF_CENTER, new Modifier("trans-off-center", _("Transform against center"), _("Change the center point when transforming objects."), SHIFT, HANDLE)}, // SCALE/ROTATE/SKEW + {Type::TRANS_SNAPPING, new Modifier("trans-snapping", _("Disable Snapping"), _("Disable snapping when transforming objects."), SHIFT, DRAG)}, // MOVE/SCALE/STRETCH/ROTATE/SKEW // Center handle click: seltrans.cpp:734 SHIFT // Align handle click: seltrans.cpp:1365 SHIFT }; @@ -115,6 +117,49 @@ std::string generate_label(KeyMask mask) return ret; } +/** + * Set the responsive tooltip for this tool, given the selected types. + * + * @param message_context - The desktop's message context for showing tooltips + * @param event - The current event status (which keys are pressed) + * @param num_args - Number of Modifier::Type arguments to follow. + * @param ... - One or more Modifier::Type arguments. + */ +void responsive_tooltip(Inkscape::MessageContext *message_context, GdkEvent *event, int num_args, ...) +{ + std::string ctrl_msg = "Ctrl: "; + std::string shift_msg = "Shift: "; + std::string alt_msg = "Alt: "; + + // NOTE: This will hide any keys changed to SUPER or multiple keys such as CTRL+SHIFT + va_list args; + va_start(args, num_args); + for(int i = 0; i < num_args; i++) { + auto modifier = Modifier::get(va_arg(args, Type)); + auto name = std::string(modifier->get_name()); + switch (modifier->get_and_mask()) { + case CTRL: + ctrl_msg += name + ", "; + break; + case SHIFT: + shift_msg += name + ", "; + break; + case ALT: + alt_msg += name + ", "; + break; + default: + g_warning("Unhandled responsivle tooltip: %s", name.c_str()); + } + } + va_end(args); + ctrl_msg.erase(ctrl_msg.size() - 2); + shift_msg.erase(shift_msg.size() - 2); + alt_msg.erase(alt_msg.size() - 2); + + Inkscape::UI::Tools::sp_event_show_modifier_tip(message_context, event, + ctrl_msg.c_str(), shift_msg.c_str(), alt_msg.c_str()); +} + } // namespace Modifiers } // namespace Inkscape diff --git a/src/ui/modifiers.h b/src/ui/modifiers.h index a44133dc12..98ac7e56dd 100644 --- a/src/ui/modifiers.h +++ b/src/ui/modifiers.h @@ -8,12 +8,15 @@ */ #include +#include #include #include #include #include +#include "message-context.h" + namespace Inkscape { namespace Modifiers { @@ -33,9 +36,6 @@ enum Key : KeyMask { enum Triggers : Trigger {CLICK, DRAG, SCROLL, HANDLE}; // TODO: We may want to further define the tool, from ANY, SELECT, NODE etc. -// Generate a label such as Shift+Ctrl from any KeyMask -std::string generate_label(KeyMask mask); - /** * This anonymous enum is used to provide a list of the Shifts */ @@ -69,6 +69,11 @@ enum class Type { }; +// Generate a label such as Shift+Ctrl from any KeyMask +std::string generate_label(KeyMask mask); +// Generate a responsivle tooltip set +void responsive_tooltip(Inkscape::MessageContext *message_context, GdkEvent *event, int num_args, ...); + /** * A class to represent ways functionality is driven by shift modifiers */ diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 5efbaa3999..b779fc18a8 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -655,10 +655,13 @@ bool SelectTool::root_handler(GdkEvent* event) { if (Inkscape::Rubberband::get(desktop)->is_started()) { Inkscape::Rubberband::get(desktop)->move(p); + auto touch_path = Modifier::get(Modifiers::Type::SELECT_TOUCH_PATH)->get_label(); if (Inkscape::Rubberband::get(desktop)->getMode() == RUBBERBAND_MODE_TOUCHPATH) { - this->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("Draw over objects to select them; release Alt to switch to rubberband selection")); + this->defaultMessageContext()->setF(Inkscape::NORMAL_MESSAGE, + _("Draw over objects to select them; release %s to switch to rubberband selection"), touch_path.c_str()); } else { - this->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("Drag around objects to select them; press Alt to switch to touch selection")); + this->defaultMessageContext()->setF(Inkscape::NORMAL_MESSAGE, + _("Drag around objects to select them; press %s to switch to touch selection"), touch_path.c_str()); } gobble_motion_events(GDK_BUTTON1_MASK); @@ -892,11 +895,11 @@ bool SelectTool::root_handler(GdkEvent* event) { break; } } else { - sp_event_show_modifier_tip (this->defaultMessageContext(), event, - _("Ctrl: click to select in groups; drag to move hor/vert"), - _("Shift: click to toggle select; drag for rubberband selection"), - _("Alt: click to select under; scroll mouse-wheel to cycle-select; drag to move selected or select by touch")); - + Modifiers::responsive_tooltip(this->defaultMessageContext(), event, 6, + Modifiers::Type::SELECT_IN_GROUPS, Modifiers::Type::MOVE_CONFINE, + Modifiers::Type::SELECT_ADD_TO, Modifiers::Type::SELECT_TOUCH_PATH, + Modifiers::Type::SELECT_CYCLE, Modifiers::Type::SELECT_FORCE_DRAG); + // if Alt and nonempty selection, show moving cursor ("move selected"): if (alt && !selection->isEmpty() && !desktop->isWaitingCursor()) { GdkWindow* window = gtk_widget_get_window (GTK_WIDGET (desktop->getCanvas()->gobj())); -- GitLab From 2594258ebc59108f087f927d187d3933316b52c9 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Tue, 25 Aug 2020 09:18:26 -0400 Subject: [PATCH 24/24] Add new translatable cpp file --- po/POTFILES.src.in | 1 + 1 file changed, 1 insertion(+) diff --git a/po/POTFILES.src.in b/po/POTFILES.src.in index f9bc268790..64569437bd 100644 --- a/po/POTFILES.src.in +++ b/po/POTFILES.src.in @@ -288,6 +288,7 @@ ../src/ui/dialog/xml-tree.cpp ../src/ui/drag-and-drop.cpp ../src/ui/interface.cpp +../src/ui/modifiers.cpp ../src/ui/shape-editor-knotholders.cpp ../src/ui/tool/curve-drag-point.cpp ../src/ui/tool/multi-path-manipulator.cpp -- GitLab