From: Soeren Apel Date: Wed, 3 Oct 2018 19:52:00 +0000 (+0200) Subject: Fix #1292/1294 by snapping to any edge when not hovering over a signal X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=f6b6c9bf50999dc99f9517318ffd3114cae4960f;p=pulseview.git Fix #1292/1294 by snapping to any edge when not hovering over a signal 1292: TimeItem instances now snap to any edge when not hovering over a signal, including the ruler itself. Hence, there is always an area where one can hover without selecting a signal, even if the entire view is full of signals. Cursors also show the desired behavior: the left edge snaps while the right does not. Hence, the width is kept constant. If the user wants to snap the right edge to a signal edge, this can be achieved by dragging the right edge separately. 1294: TimeItem instances now snap to any edge - before, they were snapping only to edges when hovering over a signal. --- diff --git a/pv/views/trace/view.cpp b/pv/views/trace/view.cpp index b8bbe357..d2d61ced 100644 --- a/pv/views/trace/view.cpp +++ b/pv/views/trace/view.cpp @@ -79,6 +79,7 @@ using std::max; using std::make_pair; using std::make_shared; using std::min; +using std::numeric_limits; using std::pair; using std::set; using std::set_difference; @@ -859,44 +860,95 @@ const QPoint& View::hover_point() const return hover_point_; } -int64_t View::get_nearest_level_change(const QPoint &p) const +int64_t View::get_nearest_level_change(const QPoint &p) { if (snap_distance_ == 0) return -1; shared_ptr signal = signal_under_mouse_cursor_; - if (!signal) - return -1; + vector nearest_edges; + int64_t nearest_sample = -1; - // Calculate sample number from cursor position - const double samples_per_pixel = signal->base()->get_samplerate() * scale(); - const int64_t x_offset = offset().convert_to() / scale(); - const int64_t sample_num = max(((x_offset + p.x()) * samples_per_pixel), 0.0); + if (signal) { + // Determine nearest edge from specific signal - // Query for nearest level changes - vector edges = - signal->get_nearest_level_changes(sample_num); + // Calculate sample number from cursor position + const double samples_per_pixel = signal->base()->get_samplerate() * scale(); + const int64_t x_offset = offset().convert_to() / scale(); + const int64_t sample_num = max(((x_offset + p.x()) * samples_per_pixel), 0.0); - if (edges.size() != 2) - return -1; + nearest_edges = signal->get_nearest_level_changes(sample_num); + + if (nearest_edges.size() != 2) + return -1; + + // We received absolute sample numbers, make them relative + const int64_t left_sample_delta = sample_num - nearest_edges.front().first; + const int64_t right_sample_delta = nearest_edges.back().first - sample_num - 1; + + const int64_t left_delta = left_sample_delta / samples_per_pixel; + const int64_t right_delta = right_sample_delta / samples_per_pixel; + + // Only use closest left or right edge if they're close to the cursor + if ((left_delta < right_delta) && (left_delta < snap_distance_)) + nearest_sample = nearest_edges.front().first; + if ((left_delta >= right_delta) && (right_delta < snap_distance_)) + nearest_sample = nearest_edges.back().first; + } else { + // Determine nearest edge from all signals + + int64_t nearest_left_delta = numeric_limits::max(); + int64_t nearest_right_delta = numeric_limits::max(); + bool edges_found = false; + + for (shared_ptr s : signals_) { + if (!s->enabled()) + continue; - // We received absolute sample numbers, make them relative - const int64_t left_sample_delta = sample_num - edges.front().first; - const int64_t right_sample_delta = edges.back().first - sample_num - 1; + // Calculate sample number from cursor position + const double samples_per_pixel = s->base()->get_samplerate() * scale(); + const int64_t x_offset = offset().convert_to() / scale(); + const int64_t sample_num = max(((x_offset + p.x()) * samples_per_pixel), 0.0); - const int64_t left_delta = left_sample_delta / samples_per_pixel; - const int64_t right_delta = right_sample_delta / samples_per_pixel; + vector edges = + s->get_nearest_level_changes(sample_num); - int64_t nearest = -1; + if (edges.size() != 2) + continue; + else + edges_found = true; + + // We received absolute sample numbers, make them relative + const int64_t left_sample_delta = sample_num - edges.front().first; + const int64_t right_sample_delta = edges.back().first - sample_num - 1; + + const int64_t left_delta = left_sample_delta / samples_per_pixel; + const int64_t right_delta = right_sample_delta / samples_per_pixel; + + if ((left_delta < nearest_left_delta) || (right_delta < nearest_right_delta)) { + nearest_edges = edges; + nearest_left_delta = left_delta; + nearest_right_delta = right_delta; + + // Somewhat ugly hack to make TimeItem::drag_by() work + signal_under_mouse_cursor_ = s; + } + } + + if (!edges_found) + return -1; - // Only use closest left or right edge if they're close to the cursor - if ((left_delta < right_delta) && (left_delta < snap_distance_)) - nearest = edges.front().first; - if ((left_delta >= right_delta) && (right_delta < snap_distance_)) - nearest = edges.back().first; + if ((nearest_left_delta < nearest_right_delta) && + (nearest_left_delta < snap_distance_)) + nearest_sample = nearest_edges.front().first; + + if ((nearest_left_delta >= nearest_right_delta) && + (nearest_right_delta < snap_distance_)) + nearest_sample = nearest_edges.back().first; + } - return nearest; + return nearest_sample; } void View::restack_all_trace_tree_items() diff --git a/pv/views/trace/view.hpp b/pv/views/trace/view.hpp index 7df0f3de..4bde31d6 100644 --- a/pv/views/trace/view.hpp +++ b/pv/views/trace/view.hpp @@ -310,7 +310,7 @@ public: * @param p The current position of the mouse cursor * @return The sample number of the nearest level change or -1 if none */ - int64_t get_nearest_level_change(const QPoint &p) const; + int64_t get_nearest_level_change(const QPoint &p); void restack_all_trace_tree_items();