13
0

refactor rubberband drags to take a functor for the no-drag condition

Also move code for adding automation line control points into automation line, rather
than in AutomationTimeAxisView (some work still required to finalize this)
This commit is contained in:
Paul Davis 2024-10-09 11:34:01 -06:00
parent e6c0fcf98f
commit 2afdeb519f
11 changed files with 116 additions and 121 deletions

View File

@ -1512,3 +1512,59 @@ AutomationLine::set_offset (timepos_t const & off)
_offset = off;
reset ();
}
void
AutomationLine::add (std::shared_ptr<AutomationControl> control, GdkEvent* event, timepos_t const & pos, double y, bool with_guard_points)
{
if (alist->in_write_pass()) {
/* do not allow the GUI to add automation events during an
automation write pass.
*/
return;
}
timepos_t when (pos);
Session* session (_editing_context.session());
_editing_context.snap_to_with_modifier (when, event);
if (UIConfiguration::instance().get_new_automation_points_on_lane() || control->list()->size () == 0) {
if (control->list()->size () == 0) {
y = control->get_value ();
} else {
y = control->list()->eval (when);
}
} else {
double x = 0;
grab_item().canvas_to_item (x, y);
/* compute vertical fractional position */
y = 1.0 - (y / height());
/* map using line */
view_to_model_coord_y (y);
}
XMLNode& before = alist->get_state();
std::list<Selectable*> results;
if (alist->editor_add (when, y, with_guard_points)) {
if (control->automation_state () == ARDOUR::Off) {
#warning paul make this work again .. call back to ATV or similar
// set_automation_state (ARDOUR::Play);
}
if (UIConfiguration::instance().get_automation_edit_cancels_auto_hide () && control == session->recently_touched_controllable ()) {
RouteTimeAxisView::signal_ctrl_touched (false);
}
XMLNode& after = alist->get_state();
_editing_context.begin_reversible_command (_("add automation event"));
_editing_context.add_command (new MementoCommand<ARDOUR::AutomationList> (*alist.get (), &before, &after));
get_selectables (when, when, 0.0, 1.0, results);
_editing_context.get_selection ().set (results);
_editing_context.commit_reversible_command ();
session->set_dirty ();
}
}

View File

@ -177,6 +177,8 @@ public:
ARDOUR::ParameterDescriptor const & param() const { return _desc; }
EditingContext& editing_context() const { return _editing_context; }
void add (std::shared_ptr<ARDOUR::AutomationControl>, GdkEvent*, Temporal::timepos_t const &, double y, bool with_guard_points);
protected:
std::string _name;

View File

@ -797,56 +797,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, timepos_t const &
return;
}
std::shared_ptr<AutomationList> list = _line->the_list ();
if (list->in_write_pass()) {
/* do not allow the GUI to add automation events during an
automation write pass.
*/
return;
}
timepos_t when (pos);
_editor.snap_to_with_modifier (when, event);
if (UIConfiguration::instance().get_new_automation_points_on_lane() || _control->list()->size () == 0) {
if (_control->list()->size () == 0) {
y = _control->get_value ();
} else {
y = _control->list()->eval (when);
}
} else {
double x = 0;
_line->grab_item().canvas_to_item (x, y);
/* compute vertical fractional position */
y = 1.0 - (y / _line->height());
/* map using line */
_line->view_to_model_coord_y (y);
}
XMLNode& before = list->get_state();
std::list<Selectable*> results;
if (list->editor_add (when, y, with_guard_points)) {
if (_control->automation_state () == ARDOUR::Off) {
set_automation_state (ARDOUR::Play);
}
if (UIConfiguration::instance().get_automation_edit_cancels_auto_hide () && _control == _session->recently_touched_controllable ()) {
RouteTimeAxisView::signal_ctrl_touched (false);
}
XMLNode& after = list->get_state();
_editor.begin_reversible_command (_("add automation event"));
_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
_line->get_selectables (when, when, 0.0, 1.0, results);
_editor.get_selection ().set (results);
_editor.commit_reversible_command ();
_session->set_dirty ();
}
_line->add (_control, event, pos, y, with_guard_points);
}
bool

View File

@ -421,8 +421,6 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
*/
void redo (uint32_t n = 1) { do_redo (n); }
virtual bool rb_click (GdkEvent*, Temporal::timepos_t const &) = 0;
virtual void history_changed() = 0;
static void update_undo_redo_actions (PBD::UndoHistory const &);

View File

@ -5163,9 +5163,10 @@ FeatureLineDrag::aborted (bool)
//_line->reset ();
}
RubberbandSelectDrag::RubberbandSelectDrag (EditingContext& ec, ArdourCanvas::Item* i)
RubberbandSelectDrag::RubberbandSelectDrag (EditingContext& ec, ArdourCanvas::Item* i, std::function<bool(GdkEvent*,timepos_t const &)> cf)
: Drag (ec, i, ec.time_domain (), ec.get_trackview_group())
, _vertical_only (false)
, click_functor (cf)
{
DEBUG_TRACE (DEBUG::Drags, "New RubberbandSelectDrag\n");
}
@ -5308,7 +5309,7 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred)
} else {
/* just a click */
bool do_deselect = editing_context.rb_click (event, grab_time());
bool do_deselect = click_functor (event, grab_time());
/* do not deselect if Primary or Tertiary (toggle-select or
* extend-select are pressed.
@ -5324,6 +5325,35 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred)
editing_context.rubberband_rect->hide ();
}
void
RubberbandSelectDrag::select_things (int button_state, timepos_t const& x1, timepos_t const& x2, double y1, double y2, bool drag_in_progress)
{
if (drag_in_progress) {
/* We just want to select things at the end of the drag, not during it */
return;
}
SelectionOperation op = ArdourKeyboard::selection_type (button_state);
editing_context.begin_reversible_selection_op (X_("rubberband selection"));
editing_context.select_all_within (x1, x2.decrement (), y1, y2, editing_context.selectable_owners(), op, false);
editing_context.commit_reversible_selection_op ();
}
void
RubberbandSelectDrag::deselect_things ()
{
editing_context.begin_reversible_selection_op (X_("Clear Selection (rubberband)"));
editing_context.get_selection().clear_tracks ();
editing_context.get_selection().clear_regions ();
editing_context.get_selection().clear_points ();
editing_context.get_selection().clear_lines ();
editing_context.get_selection().clear_midi_notes ();
editing_context.commit_reversible_selection_op ();
}
void
RubberbandSelectDrag::aborted (bool)
{
@ -6727,7 +6757,7 @@ PatchChangeDrag::setup_pointer_offset ()
}
MidiRubberbandSelectDrag::MidiRubberbandSelectDrag (EditingContext& ec, MidiView* mv)
: RubberbandSelectDrag (ec, mv->drag_group ())
: RubberbandSelectDrag (ec, mv->drag_group (), [](GdkEvent*,timepos_t const&) { return true; })
, _midi_view (mv)
{
}
@ -6747,7 +6777,7 @@ MidiRubberbandSelectDrag::deselect_things ()
}
MidiVerticalSelectDrag::MidiVerticalSelectDrag (EditingContext& ec, MidiView* mv)
: RubberbandSelectDrag (ec, mv->drag_group ())
: RubberbandSelectDrag (ec, mv->drag_group (), [](GdkEvent*,timepos_t const &) { return true; })
, _midi_view (mv)
{
_vertical_only = true;
@ -6772,40 +6802,6 @@ MidiVerticalSelectDrag::deselect_things ()
/* XXX */
}
EditorRubberbandSelectDrag::EditorRubberbandSelectDrag (EditingContext& e, ArdourCanvas::Item* i)
: RubberbandSelectDrag (e, i)
{
}
void
EditorRubberbandSelectDrag::select_things (int button_state, timepos_t const& x1, timepos_t const& x2, double y1, double y2, bool drag_in_progress)
{
if (drag_in_progress) {
/* We just want to select things at the end of the drag, not during it */
return;
}
SelectionOperation op = ArdourKeyboard::selection_type (button_state);
editing_context.begin_reversible_selection_op (X_("rubberband selection"));
editing_context.select_all_within (x1, x2.decrement (), y1, y2, editing_context.selectable_owners(), op, false);
editing_context.commit_reversible_selection_op ();
}
void
EditorRubberbandSelectDrag::deselect_things ()
{
editing_context.begin_reversible_selection_op (X_("Clear Selection (rubberband)"));
editing_context.get_selection().clear_tracks ();
editing_context.get_selection().clear_regions ();
editing_context.get_selection().clear_points ();
editing_context.get_selection().clear_lines ();
editing_context.get_selection().clear_midi_notes ();
editing_context.commit_reversible_selection_op ();
}
NoteCreateDrag::NoteCreateDrag (EditingContext& ec, ArdourCanvas::Item* i, MidiView* mv)
: Drag (ec, i, Temporal::BeatTime, ec.get_trackview_group())
, _midi_view (mv)

View File

@ -1286,7 +1286,7 @@ private:
class RubberbandSelectDrag : public Drag
{
public:
RubberbandSelectDrag (EditingContext&, ArdourCanvas::Item *);
RubberbandSelectDrag (EditingContext&, ArdourCanvas::Item *, std::function<bool(GdkEvent*,Temporal::timepos_t const &)> click_functor);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1307,35 +1307,24 @@ public:
* @param y2 The bottom of the rectangle in trackview coordinates.
* @param drag_in_progress true if the drag is currently happening.
*/
virtual void select_things (int button_state, Temporal::timepos_t const & x1, Temporal::timepos_t const & x2, double y1, double y2, bool drag_in_progress) = 0;
virtual void deselect_things () = 0;
virtual void select_things (int button_state, Temporal::timepos_t const & x1, Temporal::timepos_t const & x2, double y1, double y2, bool drag_in_progress);
virtual void deselect_things ();
protected:
bool _vertical_only;
};
/** A general editor RubberbandSelectDrag (for regions, automation points etc.) */
class EditorRubberbandSelectDrag : public RubberbandSelectDrag
{
public:
EditorRubberbandSelectDrag (EditingContext&, ArdourCanvas::Item *);
void select_things (int, Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, bool);
void deselect_things ();
private:
std::function<bool(GdkEvent*,Temporal::timepos_t const &)> click_functor;
};
/** A RubberbandSelectDrag for selecting MIDI notes */
class MidiRubberbandSelectDrag : public RubberbandSelectDrag
{
public:
public:
MidiRubberbandSelectDrag (EditingContext&, MidiView *);
void select_things (int, Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, bool);
void deselect_things ();
private:
private:
MidiView* _midi_view;
};

View File

@ -865,19 +865,19 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case StreamItem:
/* in the past, we created a new midi region here, but perhaps that is best left to the Draw mode */
/* .. now we allow for rubberband selection (region gain) */
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
_drags->set (new RubberbandSelectDrag (*this, item, [&](GdkEvent* ev, timepos_t const & pos) { return this->rb_click (ev, pos); }), event);
return true;
break;
case AutomationTrackItem:
/* rubberband drag to select automation points */
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
_drags->set (new RubberbandSelectDrag (*this, item, [&](GdkEvent* ev, timepos_t const & pos) { return this->rb_click (ev, pos); }), event);
return true;
break;
case RegionItem:
/* rubberband drag to select region gain points */
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
_drags->set (new RubberbandSelectDrag (*this, item, [&](GdkEvent* ev, timepos_t const & pos) { return this->rb_click (ev, pos); }), event);
return true;
break;
@ -890,7 +890,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) &&
event->type == GDK_BUTTON_PRESS) {
_drags->set (new EditorRubberbandSelectDrag (*this, get_trackview_group()), event);
_drags->set (new RubberbandSelectDrag (*this, get_trackview_group(), [&](GdkEvent* ev, timepos_t const & pos) { return this->rb_click (ev, pos); }), event);
} else if (event->type == GDK_BUTTON_PRESS) {
@ -1004,7 +1004,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
case StreamItem:
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
_drags->set (new RubberbandSelectDrag (*this, item, [&](GdkEvent* ev, timepos_t const & pos) { return this->rb_click (ev, pos); }), event);
return true;
case AutomationTrackItem:
@ -1032,7 +1032,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
}
} else {
/* rubberband drag to select automation points */
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
_drags->set (new RubberbandSelectDrag (*this, item, [&](GdkEvent* ev, timepos_t const & pos) { return this->rb_click (ev, pos); }), event);
}
break;
}

View File

@ -549,7 +549,7 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
switch (mouse_mode) {
case Editing::MouseContent:
/* rubberband drag to select automation points */
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
_drags->set (new RubberbandSelectDrag (*this, item, [&](GdkEvent* ev, timepos_t const & pos) { return view->automation_rb_click (ev, pos); }), event);
break;
case Editing::MouseDraw:
_drags->set (new AutomationDrawDrag (*this, nullptr, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
@ -1653,8 +1653,3 @@ MidiCueEditor::selectable_owners()
return std::list<SelectableOwner*> ();
}
bool
MidiCueEditor::rb_click (GdkEvent*, timepos_t const &)
{
return false;
}

View File

@ -100,8 +100,6 @@ class MidiCueEditor : public CueEditor
std::list<SelectableOwner*> selectable_owners();
bool rb_click (GdkEvent*, Temporal::timepos_t const &);
Gdk::Cursor* which_track_cursor () const;
Gdk::Cursor* which_mode_cursor () const;
Gdk::Cursor* which_trim_cursor (bool left_side) const;

View File

@ -309,3 +309,11 @@ MidiCueView::make_merger ()
[this](Temporal::timepos_t const& t) { return t; },
nullptr, nullptr);
}
bool
MidiCueView::automation_rb_click (GdkEvent* event, Temporal::timepos_t const & pos)
{
automation_line->add (automation_control, event, pos, 0.5, true);
return false;
}

View File

@ -59,6 +59,8 @@ class MidiCueView : public MidiView
std::list<SelectableOwner*> selectable_owners();
MergeableLine* make_merger ();
bool automation_rb_click (GdkEvent*, Temporal::timepos_t const &);
protected:
bool scroll (GdkEventScroll* ev);