Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
modifiers.h
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2#ifndef SEEN_SP_MODIFIERS_H
3#define SEEN_SP_MODIFIERS_H
4/*
5 * Copyright (C) 2020 Martin Owens <doctormo@gmail.com>
6
7 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
8 */
9
10#include <cstring>
11#include <cstdarg>
12#include <string>
13#include <vector>
14#include <map>
15
16#include <gdk/gdk.h>
17
18#include "message-context.h"
19
20namespace Inkscape {
21
22struct KeyEvent;
23
24namespace Modifiers {
25
26using KeyMask = int;
27using Trigger = int;
28
29enum Key : KeyMask {
30 NEVER = -2, // Never happen, switch off
31 NOT_SET = -1, // Not set (user or keys)
32 ALWAYS = 0, // Always happens, no modifier needed
33 SHIFT = GDK_SHIFT_MASK,
34 CTRL = GDK_CONTROL_MASK,
35 ALT = GDK_ALT_MASK,
36 SUPER = GDK_SUPER_MASK,
37 HYPER = GDK_HYPER_MASK,
38 META = GDK_META_MASK,
40};
41
42// Triggers used for collision warnings, two tools are using the same trigger
46 // Action taken to trigger this modifier, starts at
47 // bit 6 so categories and triggers can be combined.
48 CLICK = 32,
49 DRAG = 64,
50 SCROLL = 128,
51};
52
56enum class Type {
57 // {TOOL_NAME}_{ACTION_NAME}
58
59 // Canvas tools (applies to any tool selection)
60 CANVAS_PAN_Y, // Pan up and down {NOTHING+SCROLL}
61 CANVAS_PAN_X, // Pan left and right {SHIFT+SCROLL}
62 CANVAS_ZOOM, // Zoom in and out {CTRL+SCROLL}
63 CANVAS_ROTATE, // Rotate CW and CCW {CTRL+SHIFT+SCROLL}
64
65 // Select tool (minus transform)
66 SELECT_ADD_TO, // Add selection {SHIFT+CLICK}
67 SELECT_IN_GROUPS, // Select within groups {CTRL+CLICK}
68 SELECT_TOUCH_PATH, // Draw band to select {ALT+DRAG+Nothing selected}
69 SELECT_ALWAYS_BOX, // Draw box to select {SHIFT+DRAG}
70 SELECT_REMOVE_FROM, // Remove from selection {CTRL+DRAG}
71 SELECT_FORCE_DRAG, // Drag objects even if the mouse isn't over them {ALT+DRAG+Selected}
72 SELECT_CYCLE, // Cycle through objects under cursor {ALT+SCROLL}
73
74 // Transform handles (applies to multiple tools)
75 MOVE_CONFINE, // Limit dragging to X OR Y only {DRAG+CTRL}
76 MOVE_INCREMENT, // Move objects by fixed amounts {DRAG+ALT}
77 MOVE_SNAPPING, // Disable snapping while moving {DRAG+SHIFT}
78 TRANS_CONFINE, // Confine resize aspect ratio {HANDLE+CTRL}
79 TRANS_INCREMENT, // Scale/Rotate/skew by fixed ratio angles {HANDLE+ALT}
80 TRANS_OFF_CENTER, // Scale/Rotate/skew from opposite corner {HANDLE+SHIFT}
81 TRANS_SNAPPING, // Disable snapping while transforming {HANDLE+SHIFT}
82
83 BOOL_SHIFT, // Shift the shape builder into its alternative mode.
84 NODE_GROW_LINEAR, // Scroll wheel selection of nodes
85 NODE_INVERT, // Select nodes outside of the selection box
86 NODE_REMOVE_FROM, // Remove selected nodes from selection
87 NODE_GROW_SPATIAL, // Scroll wheel selection of nodes
88 // TODO: Alignment omitted because it's UX is not completed
89};
90
91// Generate a label such as Shift+Ctrl from any KeyMask
92std::string generate_label(KeyMask mask, std::string sep = "+");
93unsigned long calculate_weight(KeyMask mask);
94
95// Generate a responsivle tooltip set
96void responsive_tooltip(MessageContext *message_context, KeyEvent const &event, int num_args, ...);
97
98int add_keyval(int state, int keyval, bool release = false);
99
103class Modifier {
104private:
106 using Container = std::map<Type, Modifier>;
107 using CategoryNames = std::map<Trigger, std::string>;
108
110 static Container &_modifiers();
111 static CategoryNames const &_category_names();
112
113 char const * _id; // A unique id used by keys.xml to identify it
114 char const * _name; // A descriptive name used in preferences UI
115 char const * _desc; // A more verbose description used in preferences UI
116
117 Trigger _category; // The category of tool, what it might conflict with
118 Trigger _trigger; // The type of trigger/action
119
120 // Default values if nothing is set in keys.xml
121 KeyMask _and_mask_default; // The pressed keys must have these bits set
122 unsigned long _weight_default = 0;
123
124 // User set data, set by keys.xml (or other included file)
127 unsigned long _weight_keys = 0;
130 unsigned long _weight_user = 0;
131
132public:
133 char const * get_id() const { return _id; }
134 char const * get_name() const { return _name; }
135 char const * get_description() const { return _desc; }
136 Trigger get_trigger() const { return _category | _trigger; }
137
138 // Set user value
139 void set_keys(KeyMask and_mask, KeyMask not_mask) {
140 _and_mask_keys = and_mask;
141 _not_mask_keys = not_mask;
142 _weight_keys = calculate_weight(and_mask) + calculate_weight(not_mask);
143 }
144 void set_user(KeyMask and_mask, KeyMask not_mask) {
145 _and_mask_user = and_mask;
146 _not_mask_user = not_mask;
147 _weight_user = calculate_weight(and_mask) + calculate_weight(not_mask);
148 }
151 bool is_set_user() const { return _and_mask_user != NOT_SET; }
152
153 // Get value, either user defined value or default
157 return _and_mask_default;
158 }
160 // The not mask is enabled by the AND mask being set first.
163 return NOT_SET;
164 }
165 // Return number of bits set for the keys
166 unsigned long get_weight() const {
167 if(_and_mask_user != NOT_SET) return _weight_user;
168 if(_and_mask_keys != NOT_SET) return _weight_keys;
169 return _weight_default;
170 }
171
172 // Generate labels such as "Shift+Ctrl" for the active modifier
173 std::string get_label() const { return generate_label(get_and_mask()); }
174 std::string get_category() const { return _category_names().at(_category); }
175
176 // Configurations for saving the xml file
177 bool get_config_user_disabled() const { return (_and_mask_user == NEVER); }
178 std::string get_config_user_and() const { return generate_label(_and_mask_user, ","); }
179 std::string get_config_user_not() const { return generate_label(_not_mask_keys, ","); }
180
188 Modifier(char const * id,
189 char const * name,
190 char const * desc,
191 const KeyMask and_mask,
192 const Trigger category,
193 const Trigger trigger) :
194 _id(id),
195 _name(name),
196 _desc(desc),
197 _and_mask_default(and_mask),
198 _category(category),
199 _trigger(trigger)
200 {
202 }
203
204 static Type which(Trigger trigger, int button_state);
205 static std::vector<Modifier const *> getList();
206 bool active(int button_state) const;
207 bool active(int button_state, int keyval, bool release = false) const;
208
216 {
217 try {
218 return &_modifiers().at(index);
219 } catch (std::out_of_range const &) {
220 return nullptr;
221 }
222 }
229 static Modifier *get(char const *id);
230};
231
232} // namespace Modifiers
233} // namespace Inkscape
234
235
236#endif // SEEN_SP_MODIFIERS_H
237
238/*
239 Local Variables:
240 mode:c++
241 c-file-style:"stroustrup"
242 c-file-offsets:((innamespace . 0)(inline-open . 0))
243 indent-tabs-mode:nil
244 fill-column:99
245 End:
246*/
247// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
A convenience class for working with MessageStacks.
A class to represent ways functionality is driven by shift modifiers.
Definition modifiers.h:103
std::string get_config_user_not() const
Definition modifiers.h:179
unsigned long get_weight() const
Definition modifiers.h:166
static CategoryNames const & _category_names()
void set_user(KeyMask and_mask, KeyMask not_mask)
Definition modifiers.h:144
char const * get_name() const
Definition modifiers.h:134
bool active(int button_state) const
Test if this modifier is currently active.
KeyMask get_not_mask() const
Definition modifiers.h:159
void set_keys(KeyMask and_mask, KeyMask not_mask)
Definition modifiers.h:139
bool get_config_user_disabled() const
Definition modifiers.h:177
static Type which(Trigger trigger, int button_state)
Given a Trigger, find which modifier is active (category lookup)
std::string get_config_user_and() const
Definition modifiers.h:178
Modifier(char const *id, char const *name, char const *desc, const KeyMask and_mask, const Trigger category, const Trigger trigger)
Inititalizes the Modifier with the parameters.
Definition modifiers.h:188
static Container & _modifiers()
A table of all the created modifiers and their ID lookups.
Definition modifiers.cpp:84
std::map< Trigger, std::string > CategoryNames
Definition modifiers.h:107
std::string get_category() const
Definition modifiers.h:174
Trigger get_trigger() const
Definition modifiers.h:136
KeyMask get_and_mask() const
Definition modifiers.h:154
char const * get_id() const
Definition modifiers.h:133
char const * get_description() const
Definition modifiers.h:135
std::string get_label() const
Definition modifiers.h:173
static Modifier * get(Type index)
A function to turn an enum index into a modifier object.
Definition modifiers.h:215
std::map< Type, Modifier > Container
An easy to use definition of the table of modifiers by Type and ID.
Definition modifiers.h:106
static std::vector< Modifier const * > getList()
List all the modifiers available.
Interface for locally managing a current status message.
Type
This anonymous enum is used to provide a list of the Shifts.
Definition modifiers.h:56
int add_keyval(int state, int keyval, bool release)
Add or remove the GDK keyval to the button state if it's one of the keys that define the key mask.
unsigned long calculate_weight(KeyMask mask)
Calculate the weight of this mask based on how many bits are set.
void responsive_tooltip(MessageContext *message_context, KeyEvent const &event, int num_args,...)
Set the responsive tooltip for this tool, given the selected types.
std::string generate_label(KeyMask mask, std::string sep)
Generate a label for any modifier keys based on the mask.
Helper class to stream background task notifications as a series of messages.
A key has been pressed.
int index
Glib::ustring name
Definition toolbars.cpp:55