summaryrefslogtreecommitdiffstats
path: root/src/snap-preferences.cpp
diff options
context:
space:
mode:
authorAndrew Higginson <at.higginson@gmail.com>2011-12-27 21:04:47 +0000
committerAndrew <at.higginson@gmail.com>2011-12-27 21:04:47 +0000
commit80960b623a99aae1402ab651b2974ef544ed3b03 (patch)
treeba49d42c2789e9e11f805e2d5263e10f9fedeef8 /src/snap-preferences.cpp
parenttry to fix bug (diff)
parentGDL: Cherry-pick upstream patch 73852 (2011-03-23) - Add missing return value. (diff)
downloadinkscape-80960b623a99aae1402ab651b2974ef544ed3b03.tar.gz
inkscape-80960b623a99aae1402ab651b2974ef544ed3b03.zip
merged with trunk so I can build again...
(bzr r10092.1.36)
Diffstat (limited to 'src/snap-preferences.cpp')
-rw-r--r--src/snap-preferences.cpp301
1 files changed, 235 insertions, 66 deletions
diff --git a/src/snap-preferences.cpp b/src/snap-preferences.cpp
index 15c976466..f3df788c9 100644
--- a/src/snap-preferences.cpp
+++ b/src/snap-preferences.cpp
@@ -1,120 +1,289 @@
-#define __SNAPPREFERENCES_CPP__
-
-/**
- * \file snap-preferences.cpp
- * \brief Storing of snapping preferences
+/*
+ * Storing of snapping preferences.
*
* Authors:
* Diederik van Lierop <mail@diedenrezi.nl>
*
- * Copyright (C) 2008 Authors
+ * Copyright (C) 2008 - 2011 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "inkscape.h"
#include "snap-preferences.h"
+#include <glib.h> // g_assert()
Inkscape::SnapPreferences::SnapPreferences() :
- _include_item_center(false),
- _intersectionGG(true),
- _snap_to_grids(true),
- _snap_to_guides(true),
_snap_enabled_globally(true),
_snap_postponed_globally(false),
- _snap_to_itemnode(true), _snap_to_itempath(true),
- _snap_to_bboxnode(true), _snap_to_bboxpath(true),
- _snap_to_page_border(false),
_strict_snapping(true)
{
- setSnapFrom(SnapSourceType(SNAPSOURCE_BBOX_CATEGORY | SNAPSOURCE_NODE_CATEGORY | SNAPSOURCE_OTHER_CATEGORY), true); //Snap any point. In v0.45 and earlier, this was controlled in the preferences tab
+ // Check for powers of two; see the comments in snap-enums.h
+ g_assert((SNAPTARGET_BBOX_CATEGORY != 0) && !(SNAPTARGET_BBOX_CATEGORY & (SNAPTARGET_BBOX_CATEGORY - 1)));
+ g_assert((SNAPTARGET_NODE_CATEGORY != 0) && !(SNAPTARGET_NODE_CATEGORY & (SNAPTARGET_NODE_CATEGORY - 1)));
+ g_assert((SNAPTARGET_DATUMS_CATEGORY != 0) && !(SNAPTARGET_DATUMS_CATEGORY & (SNAPTARGET_DATUMS_CATEGORY - 1)));
+ g_assert((SNAPTARGET_OTHERS_CATEGORY != 0) && !(SNAPTARGET_OTHERS_CATEGORY & (SNAPTARGET_OTHERS_CATEGORY - 1)));
+
+ for (int n = 0; n < SNAPTARGET_MAX_ENUM_VALUE; n++) {
+ _active_snap_targets[n] = -1;
+ }
}
-/*
- * The snappers have too many parameters to adjust individually. Therefore only
- * two snapping modes are presented to the user: snapping bounding box corners (to
- * other bounding boxes, grids or guides), and/or snapping nodes (to other nodes,
- * paths, grids or guides). To select either of these modes (or both), use the
- * methods defined below: setSnapModeBBox() and setSnapModeNode().
- *
- * */
+bool Inkscape::SnapPreferences::isAnyDatumSnappable() const
+{
+ return isTargetSnappable(SNAPTARGET_GUIDE, SNAPTARGET_GRID, SNAPTARGET_PAGE_BORDER);
+}
+bool Inkscape::SnapPreferences::isAnyCategorySnappable() const
+{
+ return isTargetSnappable(SNAPTARGET_NODE_CATEGORY, SNAPTARGET_BBOX_CATEGORY, SNAPTARGET_OTHERS_CATEGORY) || isTargetSnappable(SNAPTARGET_GUIDE, SNAPTARGET_GRID, SNAPTARGET_PAGE_BORDER);
+}
-void Inkscape::SnapPreferences::setSnapModeBBox(bool enabled)
+void Inkscape::SnapPreferences::_mapTargetToArrayIndex(Inkscape::SnapTargetType &target, bool &always_on, bool &group_on) const
{
- if (enabled) {
- _snap_from = SnapSourceType(_snap_from | Inkscape::SNAPSOURCE_BBOX_CATEGORY);
- } else {
- _snap_from = SnapSourceType(_snap_from & ~Inkscape::SNAPSOURCE_BBOX_CATEGORY);
+ if (target == SNAPTARGET_BBOX_CATEGORY ||
+ target == SNAPTARGET_NODE_CATEGORY ||
+ target == SNAPTARGET_OTHERS_CATEGORY ||
+ target == SNAPTARGET_DATUMS_CATEGORY) {
+ // These main targets should be handled separately, because otherwise we might call isTargetSnappable()
+ // for them (to check whether the corresponding group is on) which would lead to an infinite recursive loop
+ always_on = (target == SNAPTARGET_DATUMS_CATEGORY);
+ group_on = true;
+ return;
+ }
+
+ if (target & SNAPTARGET_BBOX_CATEGORY) {
+ group_on = isTargetSnappable(SNAPTARGET_BBOX_CATEGORY); // Only if the group with bbox sources/targets has been enabled, then we might snap to any of the bbox targets
+
+ } else if (target & SNAPTARGET_NODE_CATEGORY) {
+ group_on = isTargetSnappable(SNAPTARGET_NODE_CATEGORY); // Only if the group with path/node sources/targets has been enabled, then we might snap to any of the nodes/paths
+ if (target == SNAPTARGET_RECT_CORNER) {
+ target = SNAPTARGET_NODE_CUSP;
+ } else if (target == SNAPTARGET_ELLIPSE_QUADRANT_POINT) {
+ target = SNAPTARGET_NODE_SMOOTH;
+ } else if (target == SNAPTARGET_PATH_GUIDE_INTERSECTION) {
+ target = SNAPTARGET_PATH_INTERSECTION;
+ }
+
+ } else if (target & SNAPTARGET_DATUMS_CATEGORY) {
+ group_on = true; // These snap targets cannot be disabled as part of a disabled group;
+ switch (target) {
+ // Some snap targets don't have their own toggle. These targets are called "secondary targets". We will re-map
+ // them to their cousin which does have a toggle, and which is called a "primary target"case SNAPTARGET_GRID_INTERSECTION:
+ case SNAPTARGET_GRID_INTERSECTION:
+ target = SNAPTARGET_GRID;
+ break;
+ case SNAPTARGET_GUIDE_INTERSECTION:
+ case SNAPTARGET_GUIDE_ORIGIN:
+ target = SNAPTARGET_GUIDE;
+ break;
+ case SNAPTARGET_PAGE_CORNER:
+ target = SNAPTARGET_PAGE_BORDER;
+ break;
+
+ // Some snap targets cannot be toggled at all, and are therefore always enabled
+ case SNAPTARGET_GRID_GUIDE_INTERSECTION:
+ always_on = true; // Doesn't have it's own button
+ break;
+
+ // These are only listed for completeness
+ case SNAPTARGET_GRID:
+ case SNAPTARGET_GUIDE:
+ case SNAPTARGET_PAGE_BORDER:
+ case SNAPTARGET_DATUMS_CATEGORY:
+ break;
+ default:
+ g_warning("Snap-preferences warning: Undefined snap target (#%i)", target);
+ break;
+ }
+
+
+ } else if (target & SNAPTARGET_OTHERS_CATEGORY) {
+ // Only if the group with "other" snap sources/targets has been enabled, then we might snap to any of those targets
+ // ... but this doesn't hold for the page border, grids, and guides
+ group_on = isTargetSnappable(SNAPTARGET_OTHERS_CATEGORY);
+ switch (target) {
+ // Some snap targets don't have their own toggle. These targets are called "secondary targets". We will re-map
+ // them to their cousin which does have a toggle, and which is called a "primary target"
+ case SNAPTARGET_TEXT_ANCHOR:
+ target = SNAPTARGET_TEXT_BASELINE;
+ break;
+
+ case SNAPTARGET_IMG_CORNER: // Doesn't have its own button, on if the group is on
+ target = SNAPTARGET_OTHERS_CATEGORY;
+ break;
+ // Some snap targets cannot be toggled at all, and are therefore always enabled
+ case SNAPTARGET_CONSTRAINED_ANGLE:
+ case SNAPTARGET_CONSTRAINT:
+ always_on = true; // Doesn't have it's own button
+ break;
+
+ // These are only listed for completeness
+ case SNAPTARGET_OBJECT_MIDPOINT:
+ case SNAPTARGET_ROTATION_CENTER:
+ case SNAPTARGET_TEXT_BASELINE:
+ case SNAPTARGET_OTHERS_CATEGORY:
+ break;
+ default:
+ g_warning("Snap-preferences warning: Undefined snap target (#%i)", target);
+ break;
+ }
+
+
+ } else if (target == SNAPTARGET_UNDEFINED ) {
+ g_warning("Snap-preferences warning: Undefined snaptarget (#%i)", target);
}
}
-bool Inkscape::SnapPreferences::getSnapModeBBox() const
+void Inkscape::SnapPreferences::setTargetSnappable(Inkscape::SnapTargetType const target, bool enabled)
{
- return (_snap_from & Inkscape::SNAPSOURCE_BBOX_CATEGORY);
+ bool always_on = false;
+ bool group_on = false; // Only needed as a dummy
+ Inkscape::SnapTargetType index = target;
+
+ _mapTargetToArrayIndex(index, always_on, group_on);
+
+ if (always_on) { // If true, then this snap target is always active and cannot be toggled
+ // Catch coding errors
+ g_warning("Snap-preferences warning: Trying to enable/disable a snap target (#%i) that's always on by definition", index);
+ } else {
+ if (index == target) { // I.e. if it has not been re-mapped, then we have a primary target at hand
+ _active_snap_targets[index] = enabled;
+ } else { // If it has been re-mapped though, then this target does not have its own toggle button and should therefore not be set
+ g_warning("Snap-preferences warning: Trying to enable/disable a secondary snap target (#%i); only primary targets can be set", index);
+ }
+ }
}
-void Inkscape::SnapPreferences::setSnapModeNode(bool enabled)
+bool Inkscape::SnapPreferences::isTargetSnappable(Inkscape::SnapTargetType const target) const
{
- if (enabled) {
- _snap_from = SnapSourceType(_snap_from | Inkscape::SNAPSOURCE_NODE_CATEGORY);
+ bool always_on = false;
+ bool group_on = false;
+ Inkscape::SnapTargetType index = target;
+
+ _mapTargetToArrayIndex(index, always_on, group_on);
+
+ if (group_on) { // If true, then this snap target is in a snap group that has been enabled (e.g. bbox group, nodes/paths group, or "others" group
+ if (always_on) { // If true, then this snap target is always active and cannot be toggled
+ return true;
+ } else {
+ if (_active_snap_targets[index] == -1) {
+ // Catch coding errors
+ g_warning("Snap-preferences warning: Using an uninitialized snap target setting (#%i)", index);
+ // This happens if setTargetSnappable() has not been called for this parameter, e.g. from within sp_namedview_set,
+ // or if this target index doesn't exist at all
+ }
+ return _active_snap_targets[index];
+ }
} else {
- _snap_from = SnapSourceType(_snap_from & ~Inkscape::SNAPSOURCE_NODE_CATEGORY);
+ return false;
}
}
-bool Inkscape::SnapPreferences::getSnapModeNode() const
-{
- return (_snap_from & Inkscape::SNAPSOURCE_NODE_CATEGORY);
+bool Inkscape::SnapPreferences::isTargetSnappable(Inkscape::SnapTargetType const target1, Inkscape::SnapTargetType const target2) const {
+ return isTargetSnappable(target1) || isTargetSnappable(target2);
}
-bool Inkscape::SnapPreferences::getSnapModeBBoxOrNodes() const
-{
- return (_snap_from & (Inkscape::SNAPSOURCE_BBOX_CATEGORY | Inkscape::SNAPSOURCE_NODE_CATEGORY) );
+bool Inkscape::SnapPreferences::isTargetSnappable(Inkscape::SnapTargetType const target1, Inkscape::SnapTargetType const target2, Inkscape::SnapTargetType const target3) const {
+ return isTargetSnappable(target1) || isTargetSnappable(target2) || isTargetSnappable(target3);
}
-bool Inkscape::SnapPreferences::getSnapModeAny() const
-{
- return (_snap_from != 0);
+bool Inkscape::SnapPreferences::isTargetSnappable(Inkscape::SnapTargetType const target1, Inkscape::SnapTargetType const target2, Inkscape::SnapTargetType const target3, Inkscape::SnapTargetType const target4) const {
+ return isTargetSnappable(target1) || isTargetSnappable(target2) || isTargetSnappable(target3) || isTargetSnappable(target4);
}
-void Inkscape::SnapPreferences::setSnapModeGuide(bool enabled)
+bool Inkscape::SnapPreferences::isTargetSnappable(Inkscape::SnapTargetType const target1, Inkscape::SnapTargetType const target2, Inkscape::SnapTargetType const target3, Inkscape::SnapTargetType const target4, Inkscape::SnapTargetType const target5) const {
+ return isTargetSnappable(target1) || isTargetSnappable(target2) || isTargetSnappable(target3) || isTargetSnappable(target4) || isTargetSnappable(target5);
+}
+
+bool Inkscape::SnapPreferences::isSnapButtonEnabled(Inkscape::SnapTargetType const target) const
{
- if (enabled) {
- _snap_from = SnapSourceType(_snap_from | Inkscape::SNAPSOURCE_OTHER_CATEGORY);
+ bool always_on = false; // Only needed as a dummy
+ bool group_on = false; // Only needed as a dummy
+ Inkscape::SnapTargetType index = target;
+
+ _mapTargetToArrayIndex(index, always_on, group_on);
+
+ if (_active_snap_targets[index] == -1) {
+ // Catch coding errors
+ g_warning("Snap-preferences warning: Using an uninitialized snap target setting (#%i)", index);
+ // This happens if setTargetSnappable() has not been called for this parameter, e.g. from within sp_namedview_set,
+ // or if this target index doesn't exist at all
} else {
- _snap_from = SnapSourceType(_snap_from & ~Inkscape::SNAPSOURCE_OTHER_CATEGORY);
+ if (index == target) { // I.e. if it has not been re-mapped, then we have a primary target at hand, which does have its own toggle button
+ return _active_snap_targets[index];
+ } else { // If it has been re-mapped though, then this target does not have its own toggle button and therefore the button status cannot be read
+ g_warning("Snap-preferences warning: Trying to determine the button status of a secondary snap target (#%i); However, only primary targets have a button", index);
+ }
}
-}
-bool Inkscape::SnapPreferences::getSnapModeGuide() const
-{
- return (_snap_from & Inkscape::SNAPSOURCE_OTHER_CATEGORY);
+ return false;
}
-/**
- * Turn on/off snapping of specific point types.
- * \param t Point type.
- * \param s true to snap to this point type, otherwise false;
- */
-void Inkscape::SnapPreferences::setSnapFrom(Inkscape::SnapSourceType t, bool s)
+Inkscape::SnapTargetType Inkscape::SnapPreferences::source2target(Inkscape::SnapSourceType source) const
{
- if (s) {
- _snap_from = SnapSourceType(_snap_from | t);
- } else {
- _snap_from = SnapSourceType(_snap_from & ~t);
+ switch (source)
+ {
+ case SNAPSOURCE_UNDEFINED:
+ return SNAPTARGET_UNDEFINED;
+ case SNAPSOURCE_BBOX_CATEGORY:
+ return SNAPTARGET_BBOX_CATEGORY;
+ case SNAPSOURCE_BBOX_CORNER:
+ return SNAPTARGET_BBOX_CORNER;
+ case SNAPSOURCE_BBOX_MIDPOINT:
+ return SNAPTARGET_BBOX_MIDPOINT;
+ case SNAPSOURCE_BBOX_EDGE_MIDPOINT:
+ return SNAPTARGET_BBOX_EDGE_MIDPOINT;
+ case SNAPSOURCE_NODE_CATEGORY:
+ return SNAPTARGET_NODE_CATEGORY;
+ case SNAPSOURCE_NODE_SMOOTH:
+ return SNAPTARGET_NODE_SMOOTH;
+ case SNAPSOURCE_NODE_CUSP:
+ return SNAPTARGET_NODE_CUSP;
+ case SNAPSOURCE_LINE_MIDPOINT:
+ return SNAPTARGET_LINE_MIDPOINT;
+ case SNAPSOURCE_PATH_INTERSECTION:
+ return SNAPTARGET_PATH_INTERSECTION;
+ case SNAPSOURCE_RECT_CORNER:
+ return SNAPTARGET_RECT_CORNER;
+ case SNAPSOURCE_ELLIPSE_QUADRANT_POINT:
+ return SNAPTARGET_ELLIPSE_QUADRANT_POINT;
+ case SNAPSOURCE_DATUMS_CATEGORY:
+ return SNAPTARGET_DATUMS_CATEGORY;
+ case SNAPSOURCE_GUIDE:
+ return SNAPTARGET_GUIDE;
+ case SNAPSOURCE_GUIDE_ORIGIN:
+ return SNAPTARGET_GUIDE_ORIGIN;
+ case SNAPSOURCE_OTHERS_CATEGORY:
+ return SNAPTARGET_OTHERS_CATEGORY;
+ case SNAPSOURCE_ROTATION_CENTER:
+ return SNAPTARGET_ROTATION_CENTER;
+ case SNAPSOURCE_OBJECT_MIDPOINT:
+ return SNAPTARGET_OBJECT_MIDPOINT;
+ case SNAPSOURCE_IMG_CORNER:
+ return SNAPTARGET_IMG_CORNER;
+ case SNAPSOURCE_TEXT_ANCHOR:
+ return SNAPTARGET_TEXT_ANCHOR;
+
+ case SNAPSOURCE_NODE_HANDLE:
+ case SNAPSOURCE_OTHER_HANDLE:
+ case SNAPSOURCE_CONVEX_HULL_CORNER:
+ // For these snapsources there doesn't exist an equivalent snap target
+ return SNAPTARGET_NODE_CATEGORY;
+ case SNAPSOURCE_GRID_PITCH:
+ return SNAPTARGET_GRID;
+ default:
+ g_warning("Mapping of snap source to snap target undefined");
+ return SNAPTARGET_UNDEFINED;
}
}
-/**
- * \param t Point type.
- * \return true if snapper will snap this type of point, otherwise false.
- */
-bool Inkscape::SnapPreferences::getSnapFrom(Inkscape::SnapSourceType t) const
+bool Inkscape::SnapPreferences::isSourceSnappable(Inkscape::SnapSourceType const source) const
{
- return (_snap_from & t);
+ return isTargetSnappable(source2target(source));
}
+
/*
Local Variables:
mode:c++