lollis: better selection algorithm during drag, plus drawn line

This commit is contained in:
Paul Davis 2023-06-23 16:47:29 -06:00
parent 91500795d8
commit 006779d4c3
2 changed files with 44 additions and 1 deletions

View File

@ -53,6 +53,8 @@ static double const lollipop_radius = 8.0;
VelocityGhostRegion::VelocityGhostRegion (MidiRegionView& mrv, TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos)
: MidiGhostRegion (mrv, tv, source_tv, initial_unit_pos)
, dragging (false)
, dragging_line (nullptr)
, last_drag_x (-1)
{
base_rect->Event.connect (sigc::mem_fun (*this, &VelocityGhostRegion::base_event));
}
@ -72,23 +74,45 @@ VelocityGhostRegion::base_event (GdkEvent* ev)
switch (ev->type) {
case GDK_MOTION_NOTIFY:
if (dragging) {
lollis_close_to_x (ev->motion.x, 20., affected_lollis);
if (last_drag_x < 0) {
lollis_close_to_x (ev->motion.x, 20., affected_lollis);
} else if (last_drag_x < ev->motion.x) {
/* rightward, "later" motion */
lollis_between (last_drag_x, ev->motion.x, affected_lollis);
} else {
/* leftward, "earlier" motion */
lollis_between (ev->motion.x, last_drag_x, affected_lollis);
}
if (!affected_lollis.empty()) {
int velocity = y_position_to_velocity (r.height() - (r.y1 - ev->motion.y));
mrv->set_velocity_for_notes (affected_lollis, velocity);
}
if (dragging) {
dragging_line->add_point (ArdourCanvas::Duple (ev->motion.x - r.x0, ev->motion.y - r.y0));
last_drag_x = ev->motion.x;
}
}
break;
case GDK_BUTTON_PRESS:
if (ev->button.button == 1) {
desensitize_lollis ();
dragging = true;
last_drag_x = -1;
if (!dragging_line) {
dragging_line = new ArdourCanvas::PolyLine (_note_group);
dragging_line->set_ignore_events (true);
dragging_line->set_outline_color (0x00ff00ff);
}
dragging_line->set (ArdourCanvas::Points());
dragging_line->show();
dragging_line->raise_to_top();
base_rect->grab();
}
break;
case GDK_BUTTON_RELEASE:
if (ev->button.button == 1) {
base_rect->ungrab();
dragging_line->hide ();
dragging = false;
sensitize_lollis ();
}
@ -284,6 +308,20 @@ VelocityGhostRegion::note_selected (NoteBase* ev)
lolli->set_outline_color (ev->selected() ? UIConfiguration::instance().color ("midi note selected outline") : 0x000000ff);
}
void
VelocityGhostRegion::lollis_between (int x0, int x1, std::vector<NoteBase*>& within)
{
for (auto & gev : events) {
ArdourCanvas::Lollipop* l = dynamic_cast<ArdourCanvas::Lollipop*> (gev.second->item);
if (l) {
ArdourCanvas::Duple pos = l->item_to_canvas (ArdourCanvas::Duple (l->x(), l->y0()));
if (pos.x >= x0 && pos.x < x1) {
within.push_back (gev.second->event);
}
}
}
}
void
VelocityGhostRegion::lollis_close_to_x (int x, double distance, std::vector<NoteBase*>& within)
{

View File

@ -21,6 +21,8 @@
#ifndef __gtk_ardour_velocity_region_view_h__
#define __gtk_ardour_velocity_region_view_h__
#include "canvas/poly_line.h"
#include "ghostregion.h"
namespace ArdourCanvas {
@ -47,11 +49,14 @@ public:
private:
bool dragging;
ArdourCanvas::PolyLine* dragging_line;
int last_drag_x;
bool base_event (GdkEvent*);
bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*);
void set_size_and_position (MidiGhostRegion::GhostEvent&);
void lollis_close_to_x (int x, double distance, std::vector<NoteBase*>& events);
void lollis_between (int x0, int x1, std::vector<NoteBase*>& events);
void desensitize_lollis ();
void sensitize_lollis ();
};