region gain and MIDI CC freehand line drawing

This involved a significant change in event handling for automation region views,
but it brings it into line with how it works for other things. On button press
we initiate a drag, then if no motion occurs, the Drag returns false during
finalization, and only then do we continue through Editor::button_release_handler()
to eventually end up in ::add_automation_event().

Although it is a substantial change, the fact that it now works the same
way for audio regions, automation regions and automation tracks seems
like a definite plus.
This commit is contained in:
Paul Davis 2023-09-30 11:09:01 -06:00
parent 6b64ebdb27
commit 18819a48a9
11 changed files with 270 additions and 46 deletions

View file

@ -38,6 +38,7 @@
#include "editor.h"
#include "editor_drag.h"
#include "gui_thread.h"
#include "mergeable_line.h"
#include "midi_automation_line.h"
#include "public_editor.h"
#include "ui_config.h"
@ -88,6 +89,8 @@ AutomationRegionView::init (bool /*wfd*/)
set_height (trackview.current_height());
set_colors ();
get_canvas_frame()->set_data ("linemerger", (LineMerger*) this);
}
void
@ -132,43 +135,37 @@ AutomationRegionView::canvas_group_event (GdkEvent* ev)
return false;
}
return RegionView::canvas_group_event (ev);
}
void
AutomationRegionView::add_automation_event (GdkEvent* ev)
{
double x = ev->button.x;
double y = ev->button.y;
/* convert to item coordinates in the time axis view */
automation_view()->canvas_display()->canvas_to_item (x, y);
/* clamp y */
y = std::max (y, 0.0);
y = std::min (y, _height - NAME_HIGHLIGHT_SIZE);
/* the time domain doesn't matter here, because the automation
* list will force the position to its own time domain when
* adding the point.
*/
PublicEditor& e = trackview.editor ();
if (ev->type == GDK_BUTTON_RELEASE &&
ev->button.button == 1 &&
(e.current_mouse_mode() == Editing::MouseDraw || e.current_mouse_mode() == Editing::MouseObject) &&
!e.drags()->active()) {
double x = ev->button.x;
double y = ev->button.y;
/* convert to item coordinates in the time axis view */
automation_view()->canvas_display()->canvas_to_item (x, y);
/* clamp y */
y = std::max (y, 0.0);
y = std::min (y, _height - NAME_HIGHLIGHT_SIZE);
/* guard points only if primary modifier is used */
bool with_guard_points = Gtkmm2ext::Keyboard::modifier_state_equals (ev->button.state, Gtkmm2ext::Keyboard::PrimaryModifier);
/* the time domain doesn't matter here, because the automation
* list will force the position to its own time domain when
* adding the point.
*/
add_automation_event (ev, timepos_t (e.pixel_to_sample (x)), y, with_guard_points);
return true;
}
return RegionView::canvas_group_event (ev);
add_automation_event (timepos_t (e.pixel_to_sample (x)), y, false);
}
/** @param when Position is global time position
* @param y y position, relative to our TimeAxisView.
*/
void
AutomationRegionView::add_automation_event (GdkEvent *, timepos_t const & w, double y, bool with_guard_points)
AutomationRegionView::add_automation_event (timepos_t const & w, double y, bool with_guard_points)
{
std::shared_ptr<Evoral::Control> c = _region->control(_parameter, true);
std::shared_ptr<ARDOUR::AutomationControl> ac = std::dynamic_pointer_cast<ARDOUR::AutomationControl>(c);
@ -352,3 +349,17 @@ AutomationRegionView::set_selected (bool yn)
group->raise_to_top ();
}
}
timepos_t
AutomationRegionView::drawn_time_filter (timepos_t const & t)
{
return timepos_t (_region->absolute_time_to_source_beats (t));
}
MergeableLine*
AutomationRegionView::make_merger()
{
std::shared_ptr<Evoral::Control> c = _region->control(_parameter, true);
std::shared_ptr<ARDOUR::AutomationControl> ac = std::dynamic_pointer_cast<ARDOUR::AutomationControl>(c);
return new MergeableLine (_line, ac, boost::bind (&AutomationRegionView::drawn_time_filter, this, _1), nullptr, nullptr);
}