diff options
author | nick_m <mainsbridge@gmail.com> | 2015-09-14 05:24:28 +1000 |
---|---|---|
committer | nick_m <mainsbridge@gmail.com> | 2015-10-20 00:53:27 +1100 |
commit | 17294ab9ec2d0b826dce88930148fda0f5e978b3 (patch) | |
tree | fbcca294ff1009370e3a12366b5fd8df17abee06 /gtk2_ardour | |
parent | 03df442d0e5878868a7bc945cf23371271e67c42 (diff) |
Make control point selection more consistent.
- disallow simultaneous events via ControlList::editor_add ()
- clicking on an automation line selects the points that define it.
- don't 'flash' a region selection when using mousedraw mode.
- cp click selection resembles region selection.
- region gain points respect snap modifier (a la automation points).
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/audio_region_view.cc | 27 | ||||
-rw-r--r-- | gtk2_ardour/automation_region_view.cc | 13 | ||||
-rw-r--r-- | gtk2_ardour/automation_time_axis.cc | 17 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.cc | 159 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 55 | ||||
-rw-r--r-- | gtk2_ardour/editor_selection.cc | 14 | ||||
-rw-r--r-- | gtk2_ardour/selection.cc | 2 |
7 files changed, 192 insertions, 95 deletions
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 706611a81d..dd15529019 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -1334,25 +1334,40 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b gain_line->view_to_model_coord (x, y); + trackview.editor ().snap_to_with_modifier (fx, ev); + /* XXX STATEFUL: can't convert to stateful diff until we can represent automation data with it. */ - trackview.editor().begin_reversible_command (_("add gain control point")); XMLNode &before = audio_region()->envelope()->get_state(); + MementoCommand<AudioRegion>* region_memento = 0; if (!audio_region()->envelope_active()) { XMLNode ®ion_before = audio_region()->get_state(); audio_region()->set_envelope_active(true); XMLNode ®ion_after = audio_region()->get_state(); - trackview.session()->add_command (new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_after)); + region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_after); } - audio_region()->envelope()->editor_add (fx, y, with_guard_points); + if (audio_region()->envelope()->editor_add (fx, y, with_guard_points)) { + XMLNode &after = audio_region()->envelope()->get_state(); + std::list<Selectable*> results; + + trackview.editor().begin_reversible_command (_("add gain control point")); + + if (region_memento) { + trackview.session()->add_command (region_memento); + } - XMLNode &after = audio_region()->envelope()->get_state(); - trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after)); - trackview.editor().commit_reversible_command (); + trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after)); + + gain_line->get_selectables (fx, fx, 0.0, 1.0, results); + trackview.editor ().get_selection ().set (results); + + trackview.editor ().commit_reversible_command (); + trackview.session ()->set_dirty (); + } } void diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index 5450815329..f1f9d68b98 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -187,17 +187,18 @@ AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double double when_d = when; _line->view_to_model_coord (when_d, y); - view->editor().begin_reversible_command (_("add automation event")); XMLNode& before = _line->the_list()->get_state(); - _line->the_list()->editor_add (when_d, y, with_guard_points); + if (_line->the_list()->editor_add (when_d, y, with_guard_points)) { + view->editor().begin_reversible_command (_("add automation event")); - XMLNode& after = _line->the_list()->get_state(); + XMLNode& after = _line->the_list()->get_state(); - view->session()->add_command (new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after)); - view->editor().commit_reversible_command (); + view->session()->add_command (new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after)); + view->editor().commit_reversible_command (); - view->session()->set_dirty (); + view->session()->set_dirty (); + } } bool diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 1c79593b34..1ff3024ac6 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -638,18 +638,21 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when, _line->view_to_model_coord (x, y); - _editor.snap_to_with_modifier (when, event); - _editor.begin_reversible_command (_("add automation event")); XMLNode& before = list->get_state(); + std::list<Selectable*> results; + if (list->editor_add (when, y, with_guard_points)) { + XMLNode& after = list->get_state(); + _editor.begin_reversible_command (_("add automation event")); + _session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after)); - list->editor_add (when, y, with_guard_points); + _line->get_selectables (when, when, 0.0, 1.0, results); + _editor.get_selection ().set (results); - XMLNode& after = list->get_state(); - _session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after)); - _editor.commit_reversible_command (); - _session->set_dirty (); + _editor.commit_reversible_command (); + _session->set_dirty (); + } } bool diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 90e4dc48e4..d3e40adf12 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -5557,108 +5557,123 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) } } - } else { + } - for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) { + if (_nothing_to_drag) { + return; + } +} - framecnt_t const half = (i->start + i->end) / 2; +void +AutomationRangeDrag::motion (GdkEvent*, bool first_move) +{ + if (_nothing_to_drag && !first_move) { + return; + } - /* find the line that this audio range starts in */ - list<Line>::iterator j = _lines.begin(); - while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) { - ++j; - } + if (first_move) { + _editor->begin_reversible_command (_("automation range move")); + + if (!_ranges.empty()) { - if (j != _lines.end()) { - boost::shared_ptr<AutomationList> the_list = j->line->the_list (); + for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) { + + framecnt_t const half = (i->start + i->end) / 2; + + /* find the line that this audio range starts in */ + list<Line>::iterator j = _lines.begin(); + while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) { + ++j; + } + + if (j != _lines.end()) { + boost::shared_ptr<AutomationList> the_list = j->line->the_list (); /* j is the line that this audio range starts in; fade into it; 64 samples length plucked out of thin air. */ - framepos_t a = i->start + 64; - if (a > half) { - a = half; - } + framepos_t a = i->start + 64; + if (a > half) { + a = half; + } - double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ()); - double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ()); + double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ()); + double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ()); - the_list->editor_add (p, value (the_list, p), false); - the_list->editor_add (q, value (the_list, q), false); - } + XMLNode &before = the_list->get_state(); + bool const add_p = the_list->editor_add (p, value (the_list, p), false); + bool const add_q = the_list->editor_add (q, value (the_list, q), false); - /* same thing for the end */ + if (add_p || add_q) { + _editor->session()->add_command ( + new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state())); + } + } - j = _lines.begin(); - while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) { - ++j; - } + /* same thing for the end */ - if (j != _lines.end()) { - boost::shared_ptr<AutomationList> the_list = j->line->the_list (); + j = _lines.begin(); + while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) { + ++j; + } - /* j is the line that this audio range starts in; fade out of it; - 64 samples length plucked out of thin air. - */ + if (j != _lines.end()) { + boost::shared_ptr<AutomationList> the_list = j->line->the_list (); - framepos_t b = i->end - 64; - if (b < half) { - b = half; - } + /* j is the line that this audio range starts in; fade out of it; + 64 samples length plucked out of thin air. + */ - double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ()); - double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ()); + framepos_t b = i->end - 64; + if (b < half) { + b = half; + } + + double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ()); + double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ()); - the_list->editor_add (p, value (the_list, p), false); - the_list->editor_add (q, value (the_list, q), false); + XMLNode &before = the_list->get_state(); + bool const add_p = the_list->editor_add (p, value (the_list, p), false); + bool const add_q = the_list->editor_add (q, value (the_list, q), false); + + if (add_p || add_q) { + _editor->session()->add_command ( + new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state())); + } + } } - } - _nothing_to_drag = true; + _nothing_to_drag = true; - /* Find all the points that should be dragged and put them in the relevant - points lists in the Line structs. - */ + /* Find all the points that should be dragged and put them in the relevant + points lists in the Line structs. + */ - for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) { + for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) { - uint32_t const N = i->line->npoints (); - for (uint32_t j = 0; j < N; ++j) { + uint32_t const N = i->line->npoints (); + for (uint32_t j = 0; j < N; ++j) { - /* here's a control point on this line */ - ControlPoint* p = i->line->nth (j); - double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b (); + /* here's a control point on this line */ + ControlPoint* p = i->line->nth (j); + double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b (); - /* see if it's inside a range */ - list<AudioRange>::const_iterator k = _ranges.begin (); - while (k != _ranges.end() && (k->start >= w || k->end <= w)) { - ++k; - } + /* see if it's inside a range */ + list<AudioRange>::const_iterator k = _ranges.begin (); + while (k != _ranges.end() && (k->start >= w || k->end <= w)) { + ++k; + } - if (k != _ranges.end()) { - /* dragging this point */ - _nothing_to_drag = false; - i->points.push_back (p); + if (k != _ranges.end()) { + /* dragging this point */ + _nothing_to_drag = false; + i->points.push_back (p); + } } } } - } - if (_nothing_to_drag) { - return; - } -} - -void -AutomationRangeDrag::motion (GdkEvent*, bool first_move) -{ - if (_nothing_to_drag) { - return; - } - - if (first_move) { - _editor->begin_reversible_command (_("automation range move")); for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) { i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state); } diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index ccf63839e2..b4e4cc81af 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -399,8 +399,9 @@ Editor::step_mouse_mode (bool next) } void -Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemType item_type) +Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { + /* in object/audition/timefx/gain-automation mode, any button press sets the selection if the object can be selected. this is a bit of hack, because @@ -472,6 +473,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp switch (item_type) { case RegionItem: + if (eff_mouse_mode == MouseDraw) { + break; + } if (press) { if (eff_mouse_mode != MouseRange) { _mouse_changed_selection = set_selected_regionview_from_click (press, op); @@ -519,6 +523,51 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp } break; + case GainLineItem: + case AutomationLineItem: + if (eff_mouse_mode != MouseRange) { + AutomationLine* al; + std::list<Selectable*> selectables; + uint32_t before, after; + framecnt_t const where = (framecnt_t) floor (event->button.x * samples_per_pixel); + + if ((al = reinterpret_cast<AutomationLine*> (item->get_data ("line")))) { + + if (!al->control_points_adjacent (where, before, after)) { + break; + } + } + + selectables.push_back (al->nth (before)); + selectables.push_back (al->nth (after)); + + switch (op) { + case Selection::Set: + if (press) { + selection->set (selectables); + _mouse_changed_selection = true; + } + break; + case Selection::Add: + if (press) { + selection->add (selectables); + _mouse_changed_selection = true; + } + break; + case Selection::Toggle: + if (press) { + selection->toggle (selectables); + _mouse_changed_selection = true; + } + break; + + case Selection::Extend: + /* XXX */ + break; + } + } + break; + case StreamItem: /* for context click, select track */ if (event->button.button == 3) { @@ -532,7 +581,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp break; case AutomationTrackItem: - set_selected_track_as_side_effect (op); + if (eff_mouse_mode != MouseDraw) { + set_selected_track_as_side_effect (op); + } break; default: diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index 3a6277ecec..27e17d5fcc 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -327,15 +327,27 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation if (!clicked_control_point) { return false; } + bool ret = false; switch (op) { case Selection::Set: - if (press) { + if (!selection->selected (clicked_control_point)) { selection->set (clicked_control_point); ret = true; + } else { + /* clicked on an already selected point */ + if (press) { + break; + } else { + if (selection->points.size() > 1) { + selection->set (clicked_control_point); + ret = true; + } + } } break; + case Selection::Add: if (press) { selection->add (clicked_control_point); diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index 784f646f39..822aca0384 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -1113,7 +1113,7 @@ Selection::set (ControlPoint* cp) clear_time (); //enforce region/object exclusivity clear_tracks(); //enforce object/track exclusivity - if (cp->get_selected()) { + if (cp->get_selected () && points.size () == 1) { return; } |