File indexing completed on 2024-04-28 04:52:27
0001 /* 0002 SPDX-FileCopyrightText: 2017 Nicolas Carion 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 #include "snapmodel.hpp" 0006 #include <QDebug> 0007 #include <climits> 0008 #include <cstdlib> 0009 0010 SnapInterface::SnapInterface() = default; 0011 SnapInterface::~SnapInterface() = default; 0012 0013 SnapModel::SnapModel() = default; 0014 0015 void SnapModel::addPoint(int position) 0016 { 0017 if (m_snaps.count(position) == 0) { 0018 m_snaps[position] = 1; 0019 } else { 0020 m_snaps[position]++; 0021 } 0022 } 0023 0024 void SnapModel::removePoint(int position) 0025 { 0026 Q_ASSERT(m_snaps.count(position) > 0); 0027 if (m_snaps[position] == 1) { 0028 m_snaps.erase(position); 0029 } else { 0030 m_snaps[position]--; 0031 } 0032 } 0033 0034 int SnapModel::getClosestPoint(int position) 0035 { 0036 if (m_snaps.empty()) { 0037 return -1; 0038 } 0039 auto it = m_snaps.lower_bound(position); 0040 long long int prev = INT_MIN, next = INT_MAX; 0041 if (it != m_snaps.end()) { 0042 next = (*it).first; 0043 } 0044 if (it != m_snaps.begin()) { 0045 --it; 0046 prev = (*it).first; 0047 } 0048 if (std::llabs(position - prev) < std::llabs(position - next)) { 0049 return int(prev); 0050 } 0051 return int(next); 0052 } 0053 0054 int SnapModel::getNextPoint(int position) 0055 { 0056 if (m_snaps.empty()) { 0057 return position; 0058 } 0059 auto it = m_snaps.lower_bound(position + 1); 0060 long long int next = position; 0061 if (it != m_snaps.end()) { 0062 next = (*it).first; 0063 } 0064 return int(next); 0065 } 0066 0067 int SnapModel::getPreviousPoint(int position) 0068 { 0069 if (m_snaps.empty()) { 0070 return 0; 0071 } 0072 auto it = m_snaps.lower_bound(position); 0073 long long int prev = 0; 0074 if (it != m_snaps.begin()) { 0075 --it; 0076 prev = (*it).first; 0077 } 0078 return int(prev); 0079 } 0080 0081 void SnapModel::ignore(const std::vector<int> &pts) 0082 { 0083 for (int pt : pts) { 0084 removePoint(pt); 0085 m_ignore.push_back(pt); 0086 } 0087 } 0088 0089 void SnapModel::unIgnore() 0090 { 0091 for (const auto &pt : m_ignore) { 0092 addPoint(pt); 0093 } 0094 m_ignore.clear(); 0095 } 0096 0097 int SnapModel::proposeSize(int in, int out, int size, bool right, int maxSnapDist) 0098 { 0099 ignore({in, out}); 0100 int proposed_size = -1; 0101 if (right) { 0102 int target_pos = in + size - 1; 0103 int snapped_pos = getClosestPoint(target_pos); 0104 if (snapped_pos != -1 && qAbs(target_pos - snapped_pos) <= maxSnapDist) { 0105 proposed_size = snapped_pos - in; 0106 } 0107 } else { 0108 int target_pos = out + 1 - size; 0109 int snapped_pos = getClosestPoint(target_pos); 0110 if (snapped_pos != -1 && qAbs(target_pos - snapped_pos) <= maxSnapDist) { 0111 proposed_size = out - snapped_pos; 0112 } 0113 } 0114 unIgnore(); 0115 return proposed_size; 0116 } 0117 0118 int SnapModel::proposeSize(int in, int out, const std::vector<int> &boundaries, int size, bool right, int maxSnapDist) 0119 { 0120 ignore(boundaries); 0121 int proposed_size = -1; 0122 if (right) { 0123 int target_pos = in + size - 1; 0124 int snapped_pos = getClosestPoint(target_pos); 0125 if (snapped_pos != -1 && qAbs(target_pos - snapped_pos) <= maxSnapDist) { 0126 proposed_size = snapped_pos - in; 0127 } 0128 } else { 0129 int target_pos = out + 1 - size; 0130 int snapped_pos = getClosestPoint(target_pos); 0131 if (snapped_pos != -1 && qAbs(target_pos - snapped_pos) <= maxSnapDist) { 0132 proposed_size = out - snapped_pos; 0133 } 0134 } 0135 unIgnore(); 0136 return proposed_size; 0137 }