#include "ardour/midi_region.h"
#include "ardour/session.h"
+#include "gtkmm2ext/keyboard.h"
+
#include "automation_region_view.h"
#include "editing.h"
#include "editor.h"
#include "i18n.h"
-AutomationRegionView::AutomationRegionView (ArdourCanvas::Group* parent,
- AutomationTimeAxisView& time_axis,
- boost::shared_ptr<ARDOUR::Region> region,
- const Evoral::Parameter& param,
- boost::shared_ptr<ARDOUR::AutomationList> list,
- double spu,
- Gdk::Color const & basic_color)
+AutomationRegionView::AutomationRegionView (ArdourCanvas::Container* parent,
+ AutomationTimeAxisView& time_axis,
+ boost::shared_ptr<ARDOUR::Region> region,
+ const Evoral::Parameter& param,
+ boost::shared_ptr<ARDOUR::AutomationList> list,
+ double spu,
+ uint32_t basic_color)
: RegionView(parent, time_axis, region, spu, basic_color, true)
+ , _region_relative_time_converter(region->session().tempo_map(), region->position())
+ , _source_relative_time_converter(region->session().tempo_map(), region->position() - region->start())
, _parameter(param)
{
if (list) {
create_line(list);
}
- group->Event.connect (sigc::mem_fun (this, &AutomationRegionView::canvas_event));
group->raise_to_top();
}
AutomationRegionView::~AutomationRegionView ()
{
+ RegionViewGoingAway (this); /* EMIT_SIGNAL */
}
void
-AutomationRegionView::init (Gdk::Color const & basic_color, bool /*wfd*/)
+AutomationRegionView::init (bool /*wfd*/)
{
_enable_display = false;
- RegionView::init(basic_color, false);
-
- compute_colors (basic_color);
+ RegionView::init (false);
reset_width_dependent_items ((double) _region->length() / samples_per_pixel);
}
bool
-AutomationRegionView::canvas_event (GdkEvent* ev)
+AutomationRegionView::canvas_group_event (GdkEvent* ev)
{
+ if (in_destructor) {
+ return false;
+ }
+
PublicEditor& e = trackview.editor ();
+ if (!trackview.editor().internal_editing() &&
+ e.current_mouse_mode() != Editing::MouseDraw) {
+ // not in internal edit mode, so just act like a normal region
+ return RegionView::canvas_group_event (ev);
+ }
+
if (ev->type == GDK_BUTTON_PRESS && e.current_mouse_mode() == Editing::MouseObject) {
/* XXX: icky dcast to Editor */
e.drags()->set (new EditorRubberbandSelectDrag (dynamic_cast<Editor*> (&e), group), ev);
+ e.drags()->start_grab (ev);
+ return true;
- } else if (ev->type == GDK_BUTTON_RELEASE) {
+ } else if (ev->type == GDK_MOTION_NOTIFY && e.drags()->active()) {
+ /* we probably shouldn't have to handle this here, but... */
+ e.drags()->motion_handler(ev, false);
+ return true;
- if (trackview.editor().drags()->active() && trackview.editor().drags()->end_grab (ev)) {
+ } else if (ev->type == GDK_BUTTON_RELEASE && e.current_mouse_mode() == Editing::MouseDraw) {
+ if (e.drags()->end_grab (ev)) {
return true;
+ } else if (e.current_mouse_mode() != Editing::MouseDraw &&
+ e.current_mouse_mode() != Editing::MouseObject) {
+ return RegionView::canvas_group_event (ev);
}
double x = ev->button.x;
y = std::max (y, 0.0);
y = std::min (y, _height - NAME_HIGHLIGHT_SIZE);
- add_automation_event (ev, trackview.editor().pixel_to_sample (x) - _region->position() + _region->start(), y);
+ /* guard points only if primary modifier is used */
+ bool with_guard_points = Gtkmm2ext::Keyboard::modifier_state_equals (ev->button.state, Gtkmm2ext::Keyboard::PrimaryModifier);
+ add_automation_event (ev, e.pixel_to_sample (x) - _region->position() + _region->start(), y, with_guard_points);
+ return true;
}
- return false;
+ return RegionView::canvas_group_event (ev);
}
/** @param when Position in frames, where 0 is the start of the region.
* @param y y position, relative to our TimeAxisView.
*/
void
-AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double y)
+AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double y, bool with_guard_points)
{
if (!_line) {
boost::shared_ptr<Evoral::Control> c = _region->control(_parameter, true);
view->session()->begin_reversible_command (_("add automation event"));
XMLNode& before = _line->the_list()->get_state();
- _line->the_list()->add (when_d, y);
+ _line->the_list()->add (when_d, y, with_guard_points, false);
XMLNode& after = _line->the_list()->get_state();
- /* XXX: hack! */
- boost::shared_ptr<ARDOUR::MidiRegion> mr = boost::dynamic_pointer_cast<ARDOUR::MidiRegion> (_region);
- assert (mr);
-
view->session()->commit_reversible_command (
- new MementoCommand<ARDOUR::AutomationList> (new ARDOUR::MidiAutomationListBinder (mr->midi_source(), _parameter), &before, &after)
- );
-
+ new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after));
view->session()->set_dirty ();
}
+bool
+AutomationRegionView::paste (framepos_t pos,
+ unsigned paste_count,
+ float times,
+ boost::shared_ptr<const ARDOUR::AutomationList> slist)
+{
+ AutomationTimeAxisView* const view = automation_view();
+ boost::shared_ptr<ARDOUR::AutomationList> my_list = _line->the_list();
+
+ if (view->session()->transport_rolling() && my_list->automation_write()) {
+ /* do not paste if this control is in write mode and we're rolling */
+ return false;
+ }
+
+ /* add multi-paste offset if applicable */
+ pos += view->editor().get_paste_offset(
+ pos, paste_count, _source_relative_time_converter.to(slist->length()));
+
+ const double model_pos = _source_relative_time_converter.from(
+ pos - _source_relative_time_converter.origin_b());
+
+ XMLNode& before = my_list->get_state();
+ my_list->paste(*slist, model_pos, times);
+ view->session()->add_command(
+ new MementoCommand<ARDOUR::AutomationList>(_line->memento_command_binder(), &before, &my_list->get_state()));
+
+ return true;
+}
+
void
AutomationRegionView::set_height (double h)
{
{
RegionView::region_resized (what_changed);
+ if (what_changed.contains (ARDOUR::Properties::position)) {
+ _region_relative_time_converter.set_origin_b(_region->position());
+ }
+
+ if (what_changed.contains (ARDOUR::Properties::start) ||
+ what_changed.contains (ARDOUR::Properties::position)) {
+ _source_relative_time_converter.set_origin_b (_region->position() - _region->start());
+ }
+
if (!_line) {
return;
}