wideranging changes to get automation editing working in cue editor
This commit is contained in:
parent
4169f11ddd
commit
90c8726c6d
@ -102,7 +102,7 @@ AutomationLineBase::AutomationLineBase (const string& name,
|
||||
, have_reset_timeout (false)
|
||||
, no_draw (false)
|
||||
, _is_boolean (false)
|
||||
, editing_context (ec)
|
||||
, _editing_context (ec)
|
||||
, _parent_group (parent)
|
||||
, _drag_base (drag_base)
|
||||
, _offset (0)
|
||||
@ -122,7 +122,7 @@ AutomationLineBase::AutomationLineBase (const string& name,
|
||||
|
||||
line->Event.connect (sigc::mem_fun (*this, &AutomationLineBase::event_handler));
|
||||
|
||||
editing_context.session()->register_with_memento_command_factory(alist->id(), this);
|
||||
_editing_context.session()->register_with_memento_command_factory(alist->id(), this);
|
||||
|
||||
interpolation_changed (alist->interpolation ());
|
||||
|
||||
@ -236,7 +236,7 @@ AutomationLineBase::control_point_box_size ()
|
||||
} else if (_height > (guint32) TimeAxisView::preset_height (HeightNormal)) {
|
||||
return rint (6.0 * uiscale);
|
||||
}
|
||||
return rint (4.0 * uiscale);
|
||||
return rint (12.0 * uiscale);
|
||||
}
|
||||
|
||||
void
|
||||
@ -311,9 +311,8 @@ AutomationLineBase::modify_points_y (std::vector<ControlPoint*> const& cps, doub
|
||||
y = min (1.0, y);
|
||||
y = _height - (y * _height);
|
||||
|
||||
editing_context.begin_reversible_command (_("automation event move"));
|
||||
editing_context.session()->add_command (
|
||||
new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
|
||||
_editing_context.begin_reversible_command (_("automation event move"));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
|
||||
|
||||
alist->freeze ();
|
||||
for (auto const& cp : cps) {
|
||||
@ -332,11 +331,10 @@ AutomationLineBase::modify_points_y (std::vector<ControlPoint*> const& cps, doub
|
||||
|
||||
update_pending = false;
|
||||
|
||||
editing_context.session()->add_command (
|
||||
new MementoCommand<AutomationList> (memento_command_binder(), 0, &alist->get_state()));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), 0, &alist->get_state()));
|
||||
|
||||
editing_context.commit_reversible_command ();
|
||||
editing_context.session()->set_dirty ();
|
||||
_editing_context.commit_reversible_command ();
|
||||
_editing_context.session()->set_dirty ();
|
||||
}
|
||||
|
||||
void
|
||||
@ -435,8 +433,7 @@ AutomationLineBase::string_to_fraction (string const & s) const
|
||||
void
|
||||
AutomationLineBase::start_drag_single (ControlPoint* cp, double x, float fraction)
|
||||
{
|
||||
editing_context.session()->add_command (
|
||||
new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
|
||||
|
||||
_drag_points.clear ();
|
||||
_drag_points.push_back (cp);
|
||||
@ -460,8 +457,7 @@ AutomationLineBase::start_drag_single (ControlPoint* cp, double x, float fractio
|
||||
void
|
||||
AutomationLineBase::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
|
||||
{
|
||||
editing_context.session()->add_command (
|
||||
new MementoCommand<AutomationList> (memento_command_binder (), &get_state(), 0));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder (), &get_state(), 0));
|
||||
|
||||
_drag_points.clear ();
|
||||
|
||||
@ -479,8 +475,7 @@ AutomationLineBase::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
|
||||
void
|
||||
AutomationLineBase::start_drag_multiple (list<ControlPoint*> cp, float fraction, XMLNode* state)
|
||||
{
|
||||
editing_context.session()->add_command (
|
||||
new MementoCommand<AutomationList> (memento_command_binder(), state, 0));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), state, 0));
|
||||
|
||||
_drag_points = cp;
|
||||
start_drag_common (0, fraction);
|
||||
@ -610,9 +605,9 @@ AutomationLineBase::dt_to_dx (timepos_t const & pos, timecnt_t const & dt)
|
||||
/* convert a shift of pos by dt into an absolute timepos */
|
||||
timepos_t const new_pos ((pos + dt + get_origin()).shift_earlier (offset()));
|
||||
/* convert to pixels */
|
||||
double px = editing_context.time_to_pixel_unrounded (new_pos);
|
||||
double px = _editing_context.time_to_pixel_unrounded (new_pos);
|
||||
/* convert back to pixels-relative-to-origin */
|
||||
px -= editing_context.time_to_pixel_unrounded (get_origin());
|
||||
px -= _editing_context.time_to_pixel_unrounded (get_origin());
|
||||
return px;
|
||||
}
|
||||
|
||||
@ -792,10 +787,9 @@ AutomationLineBase::end_drag (bool with_push, uint32_t final_index)
|
||||
line->set_steps (line_points, is_stepped());
|
||||
}
|
||||
|
||||
editing_context.session()->add_command (
|
||||
new MementoCommand<AutomationList>(memento_command_binder (), 0, &alist->get_state()));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList>(memento_command_binder (), 0, &alist->get_state()));
|
||||
|
||||
editing_context.session()->set_dirty ();
|
||||
_editing_context.session()->set_dirty ();
|
||||
did_push = false;
|
||||
|
||||
contiguous_points.clear ();
|
||||
@ -827,7 +821,7 @@ AutomationLineBase::sync_model_with_view_point (ControlPoint& cp)
|
||||
const timepos_t absolute_time = model_time + origin;
|
||||
|
||||
/* now convert to pixels relative to start of region, which matches view_x */
|
||||
const double model_x = editing_context.time_to_pixel_unrounded (absolute_time) - editing_context.time_to_pixel_unrounded (origin);
|
||||
const double model_x = _editing_context.time_to_pixel_unrounded (absolute_time) - _editing_context.time_to_pixel_unrounded (origin);
|
||||
|
||||
if (view_x != model_x) {
|
||||
|
||||
@ -840,7 +834,7 @@ AutomationLineBase::sync_model_with_view_point (ControlPoint& cp)
|
||||
* pixel_to_sample() islinear only depending on zoom level.
|
||||
*/
|
||||
|
||||
const timepos_t view_samples (editing_context.pixel_to_sample (view_x));
|
||||
const timepos_t view_samples (_editing_context.pixel_to_sample (view_x));
|
||||
|
||||
/* measure distance from RegionView origin (this preserves time domain) */
|
||||
|
||||
@ -880,7 +874,7 @@ AutomationLineBase::control_points_adjacent (double xval, uint32_t & before, uin
|
||||
ControlPoint *acp = 0;
|
||||
double unit_xval;
|
||||
|
||||
unit_xval = editing_context.sample_to_pixel_unrounded (xval);
|
||||
unit_xval = _editing_context.sample_to_pixel_unrounded (xval);
|
||||
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
|
||||
@ -936,17 +930,16 @@ AutomationLineBase::is_first_point (ControlPoint& cp)
|
||||
void
|
||||
AutomationLineBase::remove_point (ControlPoint& cp)
|
||||
{
|
||||
editing_context.begin_reversible_command (_("remove control point"));
|
||||
_editing_context.begin_reversible_command (_("remove control point"));
|
||||
XMLNode &before = alist->get_state();
|
||||
|
||||
editing_context.get_selection ().clear_points ();
|
||||
_editing_context.get_selection ().clear_points ();
|
||||
alist->erase (cp.model());
|
||||
|
||||
editing_context.session()->add_command(
|
||||
new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
|
||||
|
||||
editing_context.commit_reversible_command ();
|
||||
editing_context.session()->set_dirty ();
|
||||
_editing_context.commit_reversible_command ();
|
||||
_editing_context.session()->set_dirty ();
|
||||
}
|
||||
|
||||
/** Get selectable points within an area.
|
||||
@ -1109,7 +1102,7 @@ AutomationLineBase::reset_callback (const Evoral::ControlList& events)
|
||||
* zoom and scroll into account).
|
||||
*/
|
||||
|
||||
double px = editing_context.duration_to_pixels_unrounded (tx);
|
||||
double px = _editing_context.duration_to_pixels_unrounded (tx);
|
||||
add_visible_control_point (vp, pi, px, ty, ai, np);
|
||||
vp++;
|
||||
}
|
||||
@ -1167,7 +1160,7 @@ AutomationLineBase::reset_callback (const Evoral::ControlList& events)
|
||||
* from the last point to the very end
|
||||
*/
|
||||
|
||||
double px = editing_context.duration_to_pixels_unrounded (model_to_view_coord_x (_offset + _maximum_time));
|
||||
double px = _editing_context.duration_to_pixels_unrounded (model_to_view_coord_x (_offset + _maximum_time));
|
||||
|
||||
if (control_points[control_points.size() - 1]->get_x() != px && following != e.end()) {
|
||||
double ty = model_to_view_coord_y (e.unlocked_eval (_offset + _maximum_time));
|
||||
@ -1189,7 +1182,7 @@ AutomationLineBase::reset_callback (const Evoral::ControlList& events)
|
||||
update_visibility ();
|
||||
}
|
||||
|
||||
set_selected_points (editing_context.get_selection().points);
|
||||
set_selected_points (_editing_context.get_selection().points);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1219,7 +1212,7 @@ AutomationLineBase::queue_reset ()
|
||||
{
|
||||
/* this must be called from the GUI thread */
|
||||
|
||||
if (editing_context.session()->transport_rolling() && alist->automation_write()) {
|
||||
if (_editing_context.session()->transport_rolling() && alist->automation_write()) {
|
||||
/* automation write pass ... defer to a timeout */
|
||||
/* redraw in 1/4 second */
|
||||
if (!have_reset_timeout) {
|
||||
@ -1241,8 +1234,7 @@ AutomationLineBase::clear ()
|
||||
XMLNode &before = alist->get_state();
|
||||
alist->clear();
|
||||
|
||||
editing_context.session()->add_command (
|
||||
new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
|
||||
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -174,6 +174,7 @@ public:
|
||||
double dt_to_dx (Temporal::timepos_t const &, Temporal::timecnt_t const &);
|
||||
|
||||
ARDOUR::ParameterDescriptor const & param() const { return _desc; }
|
||||
EditingContext& editing_context() const { return _editing_context; }
|
||||
|
||||
protected:
|
||||
|
||||
@ -194,7 +195,7 @@ protected:
|
||||
/** true if we did a push at any point during the current drag */
|
||||
bool did_push;
|
||||
|
||||
EditingContext& editing_context;
|
||||
EditingContext& _editing_context;
|
||||
ArdourCanvas::Item& _parent_group;
|
||||
ArdourCanvas::Rectangle* _drag_base;
|
||||
ArdourCanvas::Container* group;
|
||||
|
@ -330,7 +330,6 @@ AutomationRegionView::entered ()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AutomationRegionView::exited ()
|
||||
{
|
||||
@ -338,6 +337,7 @@ AutomationRegionView::exited ()
|
||||
_line->track_exited();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutomationRegionView::set_selected (bool yn)
|
||||
{
|
||||
|
@ -156,11 +156,9 @@ AutomationStreamView::set_automation_state (AutoState state)
|
||||
if (region_views.empty()) {
|
||||
_pending_automation_state = state;
|
||||
} else {
|
||||
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
|
||||
|
||||
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
if ((*i)->the_list()) {
|
||||
(*i)->the_list()->set_automation_state (state);
|
||||
for (auto & line : get_lines()) {
|
||||
if (line->the_list()) {
|
||||
line->the_list()->set_automation_state (state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -222,10 +220,8 @@ AutomationStreamView::automation_state () const
|
||||
bool
|
||||
AutomationStreamView::has_automation () const
|
||||
{
|
||||
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
|
||||
|
||||
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
if ((*i)->npoints() > 0) {
|
||||
for (auto const & line : get_lines()) {
|
||||
if (line->npoints() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -239,10 +235,8 @@ AutomationStreamView::has_automation () const
|
||||
void
|
||||
AutomationStreamView::set_interpolation (AutomationList::InterpolationStyle s)
|
||||
{
|
||||
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
|
||||
|
||||
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
(*i)->the_list()->set_interpolation (s);
|
||||
for (auto & line : get_lines()) {
|
||||
line->the_list()->set_interpolation (s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,10 +258,8 @@ AutomationStreamView::interpolation () const
|
||||
void
|
||||
AutomationStreamView::clear ()
|
||||
{
|
||||
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
|
||||
|
||||
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
(*i)->clear ();
|
||||
for (auto & line : get_lines()) {
|
||||
line->clear ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,20 +284,18 @@ AutomationStreamView::get_selectables (timepos_t const & start, timepos_t const
|
||||
void
|
||||
AutomationStreamView::set_selected_points (PointSelection& ps)
|
||||
{
|
||||
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
|
||||
|
||||
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
(*i)->set_selected_points (ps);
|
||||
for (auto & line : get_lines()) {
|
||||
line->set_selected_points (ps);
|
||||
}
|
||||
}
|
||||
|
||||
list<std::shared_ptr<AutomationLine> >
|
||||
list<std::shared_ptr<AutomationLineBase> >
|
||||
AutomationStreamView::get_lines () const
|
||||
{
|
||||
list<std::shared_ptr<AutomationLine> > lines;
|
||||
list<std::shared_ptr<AutomationLineBase> > lines;
|
||||
|
||||
for (list<RegionView*>::const_iterator i = region_views.begin(); i != region_views.end(); ++i) {
|
||||
AutomationRegionView* arv = dynamic_cast<AutomationRegionView*> (*i);
|
||||
for (auto const & rv : region_views) {
|
||||
AutomationRegionView* arv = dynamic_cast<AutomationRegionView*> (rv);
|
||||
if (arv) {
|
||||
lines.push_back (arv->line());
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
void get_selectables (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, std::list<Selectable*> &, bool within = false);
|
||||
void set_selected_points (PointSelection &);
|
||||
|
||||
std::list<std::shared_ptr<AutomationLine> > get_lines () const;
|
||||
std::list<std::shared_ptr<AutomationLineBase> > get_lines () const;
|
||||
|
||||
bool paste (Temporal::timepos_t const & pos,
|
||||
unsigned paste_count,
|
||||
|
@ -1084,10 +1084,10 @@ AutomationTimeAxisView::has_automation () const
|
||||
return ( (_line && _line->npoints() > 0) || (_view && _view->has_automation()) );
|
||||
}
|
||||
|
||||
list<std::shared_ptr<AutomationLine> >
|
||||
list<std::shared_ptr<AutomationLineBase> >
|
||||
AutomationTimeAxisView::lines () const
|
||||
{
|
||||
list<std::shared_ptr<AutomationLine> > lines;
|
||||
list<std::shared_ptr<AutomationLineBase> > lines;
|
||||
|
||||
if (_line) {
|
||||
lines.push_back (_line);
|
||||
@ -1167,20 +1167,19 @@ AutomationTimeAxisView::parse_state_id (
|
||||
void
|
||||
AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
|
||||
{
|
||||
list<std::shared_ptr<AutomationLine> > lines;
|
||||
if (_line) {
|
||||
lines.push_back (_line);
|
||||
} else if (_view) {
|
||||
lines = _view->get_lines ();
|
||||
}
|
||||
list<std::shared_ptr<AutomationLineBase> > lines;
|
||||
|
||||
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
cut_copy_clear_one (**i, selection, op);
|
||||
if (_line) {
|
||||
cut_copy_clear_one (*_line, selection, op);
|
||||
} else if (_view) {
|
||||
for (auto & line : _view->get_lines ()) {
|
||||
cut_copy_clear_one (*line, selection, op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
|
||||
AutomationTimeAxisView::cut_copy_clear_one (AutomationLineBase& line, Selection& selection, CutCopyOp op)
|
||||
{
|
||||
std::shared_ptr<Evoral::ControlList> what_we_got;
|
||||
std::shared_ptr<AutomationList> alist (line.the_list());
|
||||
|
@ -54,6 +54,7 @@ class PublicEditor;
|
||||
class TimeSelection;
|
||||
class RegionSelection;
|
||||
class PointSelection;
|
||||
class AutomationLineBase;
|
||||
class AutomationLine;
|
||||
class Selection;
|
||||
class Selectable;
|
||||
@ -95,7 +96,7 @@ public:
|
||||
std::shared_ptr<AutomationLine> line() { return _line; }
|
||||
|
||||
/** @return All AutomationLines associated with this view */
|
||||
std::list<std::shared_ptr<AutomationLine> > lines () const;
|
||||
std::list<std::shared_ptr<AutomationLineBase> > lines () const;
|
||||
|
||||
AutomationStreamView* automation_view() const { return _view; }
|
||||
|
||||
@ -202,7 +203,7 @@ protected:
|
||||
|
||||
void build_display_menu ();
|
||||
|
||||
void cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp);
|
||||
void cut_copy_clear_one (AutomationLineBase&, Selection&, Editing::CutCopyOp);
|
||||
bool paste_one (Temporal::timepos_t const &, unsigned, float times, const Selection&, ItemCounts& counts, bool greedy=false);
|
||||
void route_going_away ();
|
||||
|
||||
|
@ -88,7 +88,7 @@ ControlPoint::~ControlPoint ()
|
||||
bool
|
||||
ControlPoint::event_handler (GdkEvent* event)
|
||||
{
|
||||
return PublicEditor::instance().canvas_control_point_event (event, _item, this);
|
||||
return _line.editing_context().canvas_control_point_event (event, _item, this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
#include "actions.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "automation_line_base.h"
|
||||
#include "control_point.h"
|
||||
#include "edit_note_dialog.h"
|
||||
#include "editing_context.h"
|
||||
#include "editing_convert.h"
|
||||
@ -141,6 +143,11 @@ EditingContext::EditingContext (std::string const & name)
|
||||
, autoscroll_horizontal_allowed (false)
|
||||
, autoscroll_vertical_allowed (false)
|
||||
, autoscroll_cnt (0)
|
||||
, _mouse_changed_selection (false)
|
||||
, entered_marker (nullptr)
|
||||
, entered_track (nullptr)
|
||||
, entered_regionview (nullptr)
|
||||
, clear_entered_track (false)
|
||||
{
|
||||
if (!button_bindings) {
|
||||
button_bindings = new Bindings ("editor-mouse");
|
||||
@ -2646,3 +2653,99 @@ EditingContext::get_draw_length_as_beats (bool& success, timepos_t const & posit
|
||||
return Temporal::Beats();
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::select_automation_line (GdkEventButton* event, ArdourCanvas::Item* item, ARDOUR::SelectionOperation op)
|
||||
{
|
||||
AutomationLineBase* al = reinterpret_cast<AutomationLineBase*> (item->get_data ("line"));
|
||||
std::list<Selectable*> selectables;
|
||||
double mx = event->x;
|
||||
double my = event->y;
|
||||
bool press = (event->type == GDK_BUTTON_PRESS);
|
||||
|
||||
al->grab_item().canvas_to_item (mx, my);
|
||||
|
||||
uint32_t before, after;
|
||||
samplecnt_t const where = (samplecnt_t) floor (canvas_to_timeline (mx) * samples_per_pixel);
|
||||
|
||||
if (!al || !al->control_points_adjacent (where, before, after)) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectables.push_back (al->nth (before));
|
||||
selectables.push_back (al->nth (after));
|
||||
|
||||
switch (op) {
|
||||
case SelectionSet:
|
||||
if (press) {
|
||||
selection->set (selectables);
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
break;
|
||||
case SelectionAdd:
|
||||
if (press) {
|
||||
selection->add (selectables);
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
break;
|
||||
case SelectionToggle:
|
||||
if (press) {
|
||||
selection->toggle (selectables);
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
break;
|
||||
case SelectionExtend:
|
||||
/* XXX */
|
||||
break;
|
||||
case SelectionRemove:
|
||||
/* not relevant */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset all selected points to the relevant default value */
|
||||
void
|
||||
EditingContext::reset_point_selection ()
|
||||
{
|
||||
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
|
||||
ARDOUR::AutomationList::iterator j = (*i)->model ();
|
||||
(*j)->value = (*i)->line().the_list()->descriptor ().normal;
|
||||
}
|
||||
}
|
||||
|
||||
EditingContext::EnterContext*
|
||||
EditingContext::get_enter_context(ItemType type)
|
||||
{
|
||||
for (ssize_t i = _enter_stack.size() - 1; i >= 0; --i) {
|
||||
if (_enter_stack[i].item_type == type) {
|
||||
return &_enter_stack[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EditingContext::choose_canvas_cursor_on_entry (ItemType type)
|
||||
{
|
||||
if (_drags->active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gdk::Cursor* cursor = which_canvas_cursor(type);
|
||||
|
||||
if (!_cursors->is_invalid (cursor)) {
|
||||
// Push a new enter context
|
||||
const EnterContext ctx = { type, CursorContext::create(*this, cursor) };
|
||||
_enter_stack.push_back(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::update_all_enter_cursors ()
|
||||
{
|
||||
for (auto & ec : _enter_stack) {
|
||||
ec.cursor_ctx->change(which_canvas_cursor (ec.item_type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,6 +59,7 @@ namespace Temporal {
|
||||
|
||||
class XMLNode;
|
||||
|
||||
class ControlPoint;
|
||||
class CursorContext;
|
||||
class DragManager;
|
||||
class EditorCursor;
|
||||
@ -151,13 +152,6 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
|
||||
|
||||
virtual void instant_save() = 0;
|
||||
|
||||
/** Get the topmost enter context for the given item type.
|
||||
*
|
||||
* This is used to change the cursor associated with a given enter context,
|
||||
* which may not be on the top of the stack.
|
||||
*/
|
||||
virtual EnterContext* get_enter_context(ItemType type) = 0;
|
||||
|
||||
virtual void begin_selection_op_history () = 0;
|
||||
virtual void begin_reversible_selection_op (std::string cmd_name) = 0;
|
||||
virtual void commit_reversible_selection_op () = 0;
|
||||
@ -256,6 +250,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
|
||||
virtual bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
||||
virtual bool canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
||||
virtual bool canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
||||
virtual bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*) = 0;
|
||||
|
||||
Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) const;
|
||||
Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const;
|
||||
@ -315,6 +310,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
|
||||
virtual Selection& get_selection() const { return *selection; }
|
||||
virtual Selection& get_cut_buffer () const { return *cut_buffer; }
|
||||
|
||||
void reset_point_selection ();
|
||||
|
||||
/** Set the mouse mode (gain, object, range, timefx etc.)
|
||||
* @param m Mouse mode (defined in editing_syms.h)
|
||||
* @param force Perform the effects of the change even if no change is required
|
||||
@ -329,9 +326,19 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
|
||||
* (defined in editing_syms.h)
|
||||
*/
|
||||
Editing::MouseMode current_mouse_mode () const { return mouse_mode; }
|
||||
virtual Editing::MouseMode effective_mouse_mode () const { return mouse_mode; }
|
||||
|
||||
/** @return Whether the current mouse mode is an "internal" editing mode. */
|
||||
virtual bool internal_editing() const = 0;
|
||||
|
||||
virtual bool get_smart_mode() const { return false; }
|
||||
|
||||
/** Push the appropriate enter/cursor context on item entry. */
|
||||
void choose_canvas_cursor_on_entry (ItemType);
|
||||
|
||||
/** Update all enter cursors based on current settings. */
|
||||
void update_all_enter_cursors ();
|
||||
|
||||
virtual Gdk::Cursor* get_canvas_cursor () const;
|
||||
static MouseCursors const* cursors () {
|
||||
return _cursors;
|
||||
@ -388,6 +395,20 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
|
||||
bool on_velocity_scroll_event (GdkEventScroll*);
|
||||
void pre_render ();
|
||||
|
||||
void select_automation_line (GdkEventButton*, ArdourCanvas::Item*, ARDOUR::SelectionOperation);
|
||||
|
||||
/** Get the topmost enter context for the given item type.
|
||||
*
|
||||
* This is used to change the cursor associated with a given enter context,
|
||||
* which may not be on the top of the stack.
|
||||
*/
|
||||
virtual EnterContext* get_enter_context(ItemType type);
|
||||
|
||||
virtual Gdk::Cursor* which_track_cursor () const = 0;
|
||||
virtual Gdk::Cursor* which_mode_cursor () const = 0;
|
||||
virtual Gdk::Cursor* which_trim_cursor (bool left_side) const = 0;
|
||||
virtual Gdk::Cursor* which_canvas_cursor (ItemType type) const = 0;
|
||||
|
||||
/** Undo some transactions.
|
||||
* @param n Number of transactions to undo.
|
||||
*/
|
||||
@ -652,6 +673,20 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
|
||||
uint32_t autoscroll_cnt;
|
||||
ArdourCanvas::Rect autoscroll_boundary;
|
||||
|
||||
bool _mouse_changed_selection;
|
||||
ArdourMarker* entered_marker;
|
||||
TimeAxisView* entered_track;
|
||||
/** If the mouse is over a RegionView or one of its child canvas items, this is set up
|
||||
to point to the RegionView. Otherwise it is 0.
|
||||
*/
|
||||
RegionView* entered_regionview;
|
||||
|
||||
bool clear_entered_track;
|
||||
|
||||
virtual void set_entered_track (TimeAxisView*) {};
|
||||
|
||||
std::vector<EnterContext> _enter_stack;
|
||||
|
||||
PBD::ScopedConnection escape_connection;
|
||||
virtual void escape () {}
|
||||
|
||||
@ -675,4 +710,3 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
|
||||
|
||||
|
||||
#endif /* __ardour_midi_editing_context_h__ */
|
||||
|
||||
|
@ -238,7 +238,6 @@ Editor::Editor ()
|
||||
, marker_click_behavior (MarkerClickSelectOnly)
|
||||
, _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
|
||||
, _notebook_shrunk (false)
|
||||
, entered_marker (0)
|
||||
, _show_marker_lines (false)
|
||||
, clicked_axisview (0)
|
||||
, clicked_routeview (0)
|
||||
@ -246,7 +245,6 @@ Editor::Editor ()
|
||||
, clicked_selection (0)
|
||||
, clicked_control_point (0)
|
||||
, button_release_can_deselect (true)
|
||||
, _mouse_changed_selection (false)
|
||||
, _popup_region_menu_item (0)
|
||||
, _track_canvas (0)
|
||||
, _track_canvas_viewport (0)
|
||||
@ -377,9 +375,6 @@ Editor::Editor ()
|
||||
, nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
|
||||
, current_stepping_trackview (0)
|
||||
, last_track_height_step_timestamp (0)
|
||||
, entered_track (0)
|
||||
, entered_regionview (0)
|
||||
, clear_entered_track (false)
|
||||
, _edit_point (EditAtMouse)
|
||||
, meters_running (false)
|
||||
, rhythm_ferret (0)
|
||||
|
@ -449,13 +449,6 @@ public:
|
||||
|
||||
void get_pointer_position (double &, double &) const;
|
||||
|
||||
/** Get the topmost enter context for the given item type.
|
||||
*
|
||||
* This is used to change the cursor associated with a given enter context,
|
||||
* which may not be on the top of the stack.
|
||||
*/
|
||||
EnterContext* get_enter_context(ItemType type);
|
||||
|
||||
TimeAxisView* stepping_axis_view () {
|
||||
return _stepping_axis_view;
|
||||
}
|
||||
@ -656,7 +649,6 @@ private:
|
||||
ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const;
|
||||
TempoMarker* find_marker_for_tempo (Temporal::TempoPoint const &);
|
||||
MeterMarker* find_marker_for_meter (Temporal::MeterPoint const &);
|
||||
ArdourMarker* entered_marker;
|
||||
bool _show_marker_lines;
|
||||
|
||||
typedef std::map<ARDOUR::Location*,LocationMarkers*> LocationMarkerMap;
|
||||
@ -724,7 +716,6 @@ private:
|
||||
|
||||
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
|
||||
bool button_release_can_deselect;
|
||||
bool _mouse_changed_selection;
|
||||
|
||||
void catch_vanishing_regionview (RegionView*);
|
||||
|
||||
@ -778,12 +769,6 @@ private:
|
||||
Gdk::Cursor* which_trim_cursor (bool left_side) const;
|
||||
Gdk::Cursor* which_canvas_cursor (ItemType type) const;
|
||||
|
||||
/** Push the appropriate enter/cursor context on item entry. */
|
||||
void choose_canvas_cursor_on_entry (ItemType);
|
||||
|
||||
/** Update all enter cursors based on current settings. */
|
||||
void update_all_enter_cursors ();
|
||||
|
||||
ArdourCanvas::GtkCanvas* _track_canvas;
|
||||
ArdourCanvas::GtkCanvasViewport* _track_canvas_viewport;
|
||||
|
||||
@ -1137,7 +1122,6 @@ private:
|
||||
|
||||
/* EDITING OPERATIONS */
|
||||
|
||||
void reset_point_selection ();
|
||||
void region_lock ();
|
||||
void region_unlock ();
|
||||
void toggle_region_lock ();
|
||||
@ -2070,15 +2054,6 @@ private:
|
||||
gint track_height_step_timeout();
|
||||
sigc::connection step_timeout;
|
||||
|
||||
TimeAxisView* entered_track;
|
||||
/** If the mouse is over a RegionView or one of its child canvas items, this is set up
|
||||
to point to the RegionView. Otherwise it is 0.
|
||||
*/
|
||||
RegionView* entered_regionview;
|
||||
|
||||
std::vector<EnterContext> _enter_stack;
|
||||
|
||||
bool clear_entered_track;
|
||||
bool left_track_canvas (GdkEventCrossing*);
|
||||
bool entered_track_canvas (GdkEventCrossing*);
|
||||
void set_entered_track (TimeAxisView*);
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "automation_time_axis.h"
|
||||
#include "control_point.h"
|
||||
#include "editor.h"
|
||||
#include "editing.h"
|
||||
#include "rgb_macros.h"
|
||||
@ -882,17 +883,6 @@ Editor::stop_canvas_autoscroll ()
|
||||
autoscroll_cnt = 0;
|
||||
}
|
||||
|
||||
EditingContext::EnterContext*
|
||||
Editor::get_enter_context(ItemType type)
|
||||
{
|
||||
for (ssize_t i = _enter_stack.size() - 1; i >= 0; --i) {
|
||||
if (_enter_stack[i].item_type == type) {
|
||||
return &_enter_stack[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::left_track_canvas (GdkEventCrossing* ev)
|
||||
{
|
||||
@ -1217,6 +1207,16 @@ Editor::which_track_cursor () const
|
||||
return cursor;
|
||||
}
|
||||
|
||||
double
|
||||
Editor::trackviews_height() const
|
||||
{
|
||||
if (!_trackview_group) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _visible_canvas_height - _trackview_group->canvas_origin().y;
|
||||
}
|
||||
|
||||
Gdk::Cursor*
|
||||
Editor::which_canvas_cursor(ItemType type) const
|
||||
{
|
||||
@ -1387,36 +1387,242 @@ Editor::which_canvas_cursor(ItemType type) const
|
||||
return cursor;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::choose_canvas_cursor_on_entry (ItemType type)
|
||||
bool
|
||||
Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
||||
{
|
||||
if (_drags->active()) {
|
||||
return;
|
||||
ControlPoint* cp;
|
||||
ArdourMarker * marker;
|
||||
MeterMarker* m_marker = 0;
|
||||
TempoMarker* t_marker = 0;
|
||||
double fraction;
|
||||
bool ret = true;
|
||||
|
||||
/* by the time we reach here, entered_regionview and entered trackview
|
||||
* will have already been set as appropriate. Things are done this
|
||||
* way because this method isn't passed a pointer to a variable type of
|
||||
* thing that is entered (which may or may not be canvas item).
|
||||
* (e.g. the actual entered regionview)
|
||||
*/
|
||||
|
||||
choose_canvas_cursor_on_entry (item_type);
|
||||
|
||||
switch (item_type) {
|
||||
case GridZoneItem:
|
||||
break;
|
||||
|
||||
case ControlPointItem:
|
||||
if (mouse_mode == MouseDraw || mouse_mode == MouseObject || mouse_mode == MouseContent) {
|
||||
cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
|
||||
cp->show ();
|
||||
|
||||
fraction = 1.0 - (cp->get_y() / cp->line().height());
|
||||
|
||||
_verbose_cursor->set (cp->line().get_verbose_cursor_string (fraction));
|
||||
_verbose_cursor->show ();
|
||||
}
|
||||
break;
|
||||
|
||||
case GainLineItem:
|
||||
if (mouse_mode == MouseDraw) {
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
if (line) {
|
||||
line->set_outline_color (UIConfiguration::instance().color ("entered gain line"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AutomationLineItem:
|
||||
if (mouse_mode == MouseDraw || mouse_mode == MouseObject) {
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
if (line) {
|
||||
line->set_outline_color (UIConfiguration::instance().color ("entered automation line"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
AutomationTimeAxisView* atv;
|
||||
if ((atv = static_cast<AutomationTimeAxisView*>(item->get_data ("trackview"))) != 0) {
|
||||
clear_entered_track = false;
|
||||
set_entered_track (atv);
|
||||
}
|
||||
break;
|
||||
|
||||
case MarkerItem:
|
||||
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = marker;
|
||||
marker->set_entered (true);
|
||||
break;
|
||||
|
||||
case MeterMarkerItem:
|
||||
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = m_marker;
|
||||
/* "music" currently serves as a stand-in for "entered". */
|
||||
m_marker->set_color ("meter marker music");
|
||||
break;
|
||||
|
||||
case TempoMarkerItem:
|
||||
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = t_marker;
|
||||
/* "music" currently serves as a stand-in for "entered". */
|
||||
t_marker->set_color ("tempo marker music");
|
||||
break;
|
||||
|
||||
case FadeInHandleItem:
|
||||
case FadeInTrimHandleItem:
|
||||
if (mouse_mode == MouseObject) {
|
||||
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
|
||||
if (rect) {
|
||||
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
|
||||
rect->set_fill_color (rv->get_fill_color());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FadeOutHandleItem:
|
||||
case FadeOutTrimHandleItem:
|
||||
if (mouse_mode == MouseObject) {
|
||||
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
|
||||
if (rect) {
|
||||
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
|
||||
rect->set_fill_color (rv->get_fill_color ());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FeatureLineItem:
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
line->set_outline_color (0xFF0000FF);
|
||||
}
|
||||
break;
|
||||
|
||||
case SelectionItem:
|
||||
break;
|
||||
|
||||
case WaveItem:
|
||||
{
|
||||
if (entered_regionview) {
|
||||
entered_regionview->entered();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Gdk::Cursor* cursor = which_canvas_cursor(type);
|
||||
/* third pass to handle entered track status in a comprehensible way.
|
||||
*/
|
||||
|
||||
if (!_cursors->is_invalid (cursor)) {
|
||||
// Push a new enter context
|
||||
const EnterContext ctx = { type, CursorContext::create(*this, cursor) };
|
||||
_enter_stack.push_back(ctx);
|
||||
switch (item_type) {
|
||||
case GainLineItem:
|
||||
case AutomationLineItem:
|
||||
case ControlPointItem:
|
||||
/* these do not affect the current entered track state */
|
||||
clear_entered_track = false;
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
/* handled above already */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::update_all_enter_cursors ()
|
||||
bool
|
||||
Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
|
||||
{
|
||||
for (auto & ec : _enter_stack) {
|
||||
ec.cursor_ctx->change(which_canvas_cursor (ec.item_type));
|
||||
}
|
||||
}
|
||||
AutomationLine* al;
|
||||
ArdourMarker *marker;
|
||||
TempoMarker *t_marker;
|
||||
MeterMarker *m_marker;
|
||||
bool ret = true;
|
||||
|
||||
double
|
||||
Editor::trackviews_height() const
|
||||
{
|
||||
if (!_trackview_group) {
|
||||
return 0;
|
||||
if (!_enter_stack.empty()) {
|
||||
_enter_stack.pop_back();
|
||||
}
|
||||
|
||||
return _visible_canvas_height - _trackview_group->canvas_origin().y;
|
||||
switch (item_type) {
|
||||
case GridZoneItem:
|
||||
break;
|
||||
|
||||
case ControlPointItem:
|
||||
_verbose_cursor->hide ();
|
||||
break;
|
||||
|
||||
case GainLineItem:
|
||||
case AutomationLineItem:
|
||||
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
if (line) {
|
||||
line->set_outline_color (al->get_line_color());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MarkerItem:
|
||||
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = 0;
|
||||
marker->set_entered (false);
|
||||
break;
|
||||
|
||||
case MeterMarkerItem:
|
||||
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
m_marker->set_color ("meter marker");
|
||||
entered_marker = 0;
|
||||
break;
|
||||
|
||||
case TempoMarkerItem:
|
||||
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
t_marker->set_color ("tempo marker");
|
||||
entered_marker = 0;
|
||||
break;
|
||||
|
||||
case FadeInTrimHandleItem:
|
||||
case FadeOutTrimHandleItem:
|
||||
case FadeInHandleItem:
|
||||
case FadeOutHandleItem:
|
||||
{
|
||||
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
|
||||
if (rect) {
|
||||
rect->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
break;
|
||||
|
||||
case FeatureLineItem:
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
line->set_outline_color (UIConfiguration::instance().color ("zero line"));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_region_peak_cursor->hide ();
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -4775,8 +4775,8 @@ MarkerDrag::update_item (Location*)
|
||||
/* noop */
|
||||
}
|
||||
|
||||
ControlPointDrag::ControlPointDrag (Editor& e, ArdourCanvas::Item* i)
|
||||
: EditorDrag (e, i, e.time_domain (), e.get_trackview_group(), false)
|
||||
ControlPointDrag::ControlPointDrag (EditingContext& e, ArdourCanvas::Item* i)
|
||||
: Drag (e, i, e.time_domain (), e.get_trackview_group(), false)
|
||||
, _fixed_grab_x (0.0)
|
||||
, _fixed_grab_y (0.0)
|
||||
, _cumulative_y_drag (0.0)
|
||||
@ -4787,7 +4787,7 @@ ControlPointDrag::ControlPointDrag (Editor& e, ArdourCanvas::Item* i)
|
||||
_zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain ());
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::Drags, "New ControlPointDrag\n");
|
||||
DEBUG_TRACE (DEBUG::Drags, string_compose ("New ControlPointDrag @ %1\n", this));
|
||||
|
||||
_point = reinterpret_cast<ControlPoint*> (_item->get_data ("control_point"));
|
||||
assert (_point);
|
||||
@ -4911,7 +4911,7 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||
if (!movement_occurred) {
|
||||
/* just a click */
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
|
||||
_editor.reset_point_selection ();
|
||||
editing_context.reset_point_selection ();
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -4935,7 +4935,7 @@ ControlPointDrag::active (Editing::MouseMode m)
|
||||
}
|
||||
|
||||
/* otherwise active if the point is on an automation line (ie not if its on a region gain line) */
|
||||
return dynamic_cast<AutomationLine*> (&(_point->line ())) != 0;
|
||||
return dynamic_cast<AutomationLineBase*> (&(_point->line ())) != 0;
|
||||
}
|
||||
|
||||
LineDrag::LineDrag (Editor& e, ArdourCanvas::Item* i)
|
||||
@ -4962,7 +4962,7 @@ LineDrag::~LineDrag ()
|
||||
void
|
||||
LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
|
||||
{
|
||||
_line = reinterpret_cast<AutomationLine*> (_item->get_data ("line"));
|
||||
_line = reinterpret_cast<AutomationLineBase*> (_item->get_data ("line"));
|
||||
assert (_line);
|
||||
|
||||
_item = &_line->grab_item ();
|
||||
@ -6399,7 +6399,7 @@ AutomationRangeDrag::AutomationRangeDrag (EditingContext& ec, list<RegionView*>
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n");
|
||||
|
||||
list<std::shared_ptr<AutomationLine>> lines;
|
||||
list<std::shared_ptr<AutomationLineBase>> lines;
|
||||
|
||||
for (list<RegionView*>::const_iterator i = v.begin (); i != v.end (); ++i) {
|
||||
if (AudioRegionView* audio_view = dynamic_cast<AudioRegionView*> (*i)) {
|
||||
@ -6418,12 +6418,12 @@ AutomationRangeDrag::AutomationRangeDrag (EditingContext& ec, list<RegionView*>
|
||||
* @param offset Offset from the session start to the points in the AutomationLines.
|
||||
*/
|
||||
void
|
||||
AutomationRangeDrag::setup (list<std::shared_ptr<AutomationLine>> const& lines)
|
||||
AutomationRangeDrag::setup (list<std::shared_ptr<AutomationLineBase>> const& lines)
|
||||
{
|
||||
/* find the lines that overlap the ranges being dragged */
|
||||
list<std::shared_ptr<AutomationLine>>::const_iterator i = lines.begin ();
|
||||
list<std::shared_ptr<AutomationLineBase>>::const_iterator i = lines.begin ();
|
||||
while (i != lines.end ()) {
|
||||
list<std::shared_ptr<AutomationLine>>::const_iterator j = i;
|
||||
list<std::shared_ptr<AutomationLineBase>>::const_iterator j = i;
|
||||
++j;
|
||||
|
||||
pair<timepos_t, timepos_t> r = (*i)->get_point_x_range ();
|
||||
|
@ -84,7 +84,7 @@ class TempoMarker;
|
||||
class TempoCurve;
|
||||
class ControlPoint;
|
||||
class AudioRegionView;
|
||||
class AutomationLine;
|
||||
class AutomationLineBase;
|
||||
class AutomationTimeAxisView;
|
||||
class VelocityDisplay;
|
||||
|
||||
@ -1202,10 +1202,10 @@ private:
|
||||
};
|
||||
|
||||
/** Control point drag */
|
||||
class ControlPointDrag : public EditorDrag
|
||||
class ControlPointDrag : public Drag
|
||||
{
|
||||
public:
|
||||
ControlPointDrag (Editor&, ArdourCanvas::Item *);
|
||||
ControlPointDrag (EditingContext&, ArdourCanvas::Item *);
|
||||
|
||||
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
|
||||
void motion (GdkEvent *, bool);
|
||||
@ -1250,7 +1250,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
AutomationLine* _line;
|
||||
AutomationLineBase* _line;
|
||||
double _fixed_grab_x;
|
||||
double _fixed_grab_y;
|
||||
double _cumulative_y_drag;
|
||||
@ -1487,7 +1487,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void setup (std::list<std::shared_ptr<AutomationLine> > const &);
|
||||
void setup (std::list<std::shared_ptr<AutomationLineBase> > const &);
|
||||
double y_fraction (double global_y_position) const;
|
||||
double value (std::shared_ptr<ARDOUR::AutomationList> list, Temporal::timepos_t const & x) const;
|
||||
|
||||
@ -1495,7 +1495,7 @@ private:
|
||||
|
||||
/** A line that is part of the drag */
|
||||
struct Line {
|
||||
std::shared_ptr<AutomationLine> line; ///< the line
|
||||
std::shared_ptr<AutomationLineBase> line; ///< the line
|
||||
std::list<ControlPoint*> points; ///< points to drag on the line
|
||||
std::pair<Temporal::timepos_t, Temporal::timepos_t> range; ///< the range of all points on the line, in session time
|
||||
XMLNode* state; ///< the XML state node before the drag
|
||||
|
@ -561,49 +561,7 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
|
||||
|
||||
case AutomationLineItem:
|
||||
if (eff_mouse_mode != MouseRange && eff_mouse_mode != MouseDraw) {
|
||||
AutomationLine* al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
|
||||
std::list<Selectable*> selectables;
|
||||
double mx = event->button.x;
|
||||
double my = event->button.y;
|
||||
|
||||
al->grab_item().canvas_to_item (mx, my);
|
||||
|
||||
uint32_t before, after;
|
||||
samplecnt_t const where = (samplecnt_t) floor (mx * samples_per_pixel);
|
||||
|
||||
if (!al || !al->control_points_adjacent (where, before, after)) {
|
||||
break;
|
||||
}
|
||||
|
||||
selectables.push_back (al->nth (before));
|
||||
selectables.push_back (al->nth (after));
|
||||
|
||||
switch (op) {
|
||||
case SelectionSet:
|
||||
if (press) {
|
||||
selection->set (selectables);
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
break;
|
||||
case SelectionAdd:
|
||||
if (press) {
|
||||
selection->add (selectables);
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
break;
|
||||
case SelectionToggle:
|
||||
if (press) {
|
||||
selection->toggle (selectables);
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
break;
|
||||
case SelectionExtend:
|
||||
/* XXX */
|
||||
break;
|
||||
case SelectionRemove:
|
||||
/* not relevant */
|
||||
break;
|
||||
}
|
||||
select_automation_line (&event->button, item, op);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1845,245 +1803,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
||||
{
|
||||
ControlPoint* cp;
|
||||
ArdourMarker * marker;
|
||||
MeterMarker* m_marker = 0;
|
||||
TempoMarker* t_marker = 0;
|
||||
double fraction;
|
||||
bool ret = true;
|
||||
|
||||
/* by the time we reach here, entered_regionview and entered trackview
|
||||
* will have already been set as appropriate. Things are done this
|
||||
* way because this method isn't passed a pointer to a variable type of
|
||||
* thing that is entered (which may or may not be canvas item).
|
||||
* (e.g. the actual entered regionview)
|
||||
*/
|
||||
|
||||
choose_canvas_cursor_on_entry (item_type);
|
||||
|
||||
switch (item_type) {
|
||||
case GridZoneItem:
|
||||
break;
|
||||
|
||||
case ControlPointItem:
|
||||
if (mouse_mode == MouseDraw || mouse_mode == MouseObject || mouse_mode == MouseContent) {
|
||||
cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
|
||||
cp->show ();
|
||||
|
||||
fraction = 1.0 - (cp->get_y() / cp->line().height());
|
||||
|
||||
_verbose_cursor->set (cp->line().get_verbose_cursor_string (fraction));
|
||||
_verbose_cursor->show ();
|
||||
}
|
||||
break;
|
||||
|
||||
case GainLineItem:
|
||||
if (mouse_mode == MouseDraw) {
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
if (line) {
|
||||
line->set_outline_color (UIConfiguration::instance().color ("entered gain line"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AutomationLineItem:
|
||||
if (mouse_mode == MouseDraw || mouse_mode == MouseObject) {
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
if (line) {
|
||||
line->set_outline_color (UIConfiguration::instance().color ("entered automation line"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
AutomationTimeAxisView* atv;
|
||||
if ((atv = static_cast<AutomationTimeAxisView*>(item->get_data ("trackview"))) != 0) {
|
||||
clear_entered_track = false;
|
||||
set_entered_track (atv);
|
||||
}
|
||||
break;
|
||||
|
||||
case MarkerItem:
|
||||
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = marker;
|
||||
marker->set_entered (true);
|
||||
break;
|
||||
|
||||
case MeterMarkerItem:
|
||||
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = m_marker;
|
||||
/* "music" currently serves as a stand-in for "entered". */
|
||||
m_marker->set_color ("meter marker music");
|
||||
break;
|
||||
|
||||
case TempoMarkerItem:
|
||||
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = t_marker;
|
||||
/* "music" currently serves as a stand-in for "entered". */
|
||||
t_marker->set_color ("tempo marker music");
|
||||
break;
|
||||
|
||||
case FadeInHandleItem:
|
||||
case FadeInTrimHandleItem:
|
||||
if (mouse_mode == MouseObject) {
|
||||
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
|
||||
if (rect) {
|
||||
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
|
||||
rect->set_fill_color (rv->get_fill_color());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FadeOutHandleItem:
|
||||
case FadeOutTrimHandleItem:
|
||||
if (mouse_mode == MouseObject) {
|
||||
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
|
||||
if (rect) {
|
||||
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
|
||||
rect->set_fill_color (rv->get_fill_color ());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FeatureLineItem:
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
line->set_outline_color (0xFF0000FF);
|
||||
}
|
||||
break;
|
||||
|
||||
case SelectionItem:
|
||||
break;
|
||||
|
||||
case WaveItem:
|
||||
{
|
||||
if (entered_regionview) {
|
||||
entered_regionview->entered();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* third pass to handle entered track status in a comprehensible way.
|
||||
*/
|
||||
|
||||
switch (item_type) {
|
||||
case GainLineItem:
|
||||
case AutomationLineItem:
|
||||
case ControlPointItem:
|
||||
/* these do not affect the current entered track state */
|
||||
clear_entered_track = false;
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
/* handled above already */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
|
||||
{
|
||||
AutomationLine* al;
|
||||
ArdourMarker *marker;
|
||||
TempoMarker *t_marker;
|
||||
MeterMarker *m_marker;
|
||||
bool ret = true;
|
||||
|
||||
if (!_enter_stack.empty()) {
|
||||
_enter_stack.pop_back();
|
||||
}
|
||||
|
||||
switch (item_type) {
|
||||
case GridZoneItem:
|
||||
break;
|
||||
|
||||
case ControlPointItem:
|
||||
_verbose_cursor->hide ();
|
||||
break;
|
||||
|
||||
case GainLineItem:
|
||||
case AutomationLineItem:
|
||||
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
if (line) {
|
||||
line->set_outline_color (al->get_line_color());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MarkerItem:
|
||||
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
entered_marker = 0;
|
||||
marker->set_entered (false);
|
||||
break;
|
||||
|
||||
case MeterMarkerItem:
|
||||
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
m_marker->set_color ("meter marker");
|
||||
entered_marker = 0;
|
||||
break;
|
||||
|
||||
case TempoMarkerItem:
|
||||
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
|
||||
break;
|
||||
}
|
||||
t_marker->set_color ("tempo marker");
|
||||
entered_marker = 0;
|
||||
break;
|
||||
|
||||
case FadeInTrimHandleItem:
|
||||
case FadeOutTrimHandleItem:
|
||||
case FadeInHandleItem:
|
||||
case FadeOutHandleItem:
|
||||
{
|
||||
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
|
||||
if (rect) {
|
||||
rect->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
break;
|
||||
|
||||
case FeatureLineItem:
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
line->set_outline_color (UIConfiguration::instance().color ("zero line"));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_region_peak_cursor->hide ();
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GridType
|
||||
Editor::determine_mapping_grid_snap(timepos_t t)
|
||||
|
@ -5708,16 +5708,6 @@ Editor::duplicate_selection (float times)
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset all selected points to the relevant default value */
|
||||
void
|
||||
Editor::reset_point_selection ()
|
||||
{
|
||||
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
|
||||
ARDOUR::AutomationList::iterator j = (*i)->model ();
|
||||
(*j)->value = (*i)->line().the_list()->descriptor ().normal;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::center_playhead ()
|
||||
{
|
||||
|
@ -16,6 +16,11 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "canvas/rectangle.h"
|
||||
|
||||
#include "editing_context.h"
|
||||
#include "editor_drag.h"
|
||||
#include "keyboard.h"
|
||||
#include "midi_cue_automation_line.h"
|
||||
|
||||
MidiCueAutomationLine::MidiCueAutomationLine (const std::string& name,
|
||||
@ -26,10 +31,18 @@ MidiCueAutomationLine::MidiCueAutomationLine (const std::string&
|
||||
const ARDOUR::ParameterDescriptor& desc)
|
||||
: AutomationLineBase (name, ec, parent, drag_base, al, desc)
|
||||
{
|
||||
_drag_base->set_data ("line", this);
|
||||
_drag_base->Event.connect (sigc::mem_fun (*this, &MidiCueAutomationLine::base_event_handler));
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueAutomationLine::event_handler (GdkEvent*)
|
||||
MidiCueAutomationLine::base_event_handler (GdkEvent* ev)
|
||||
{
|
||||
return true;
|
||||
return _editing_context.typed_event (_drag_base, ev, AutomationTrackItem);
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueAutomationLine::event_handler (GdkEvent* ev)
|
||||
{
|
||||
return _editing_context.typed_event (line, ev, AutomationLineItem);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ class MidiCueAutomationLine : public AutomationLineBase
|
||||
std::shared_ptr<ARDOUR::AutomationList> al,
|
||||
const ARDOUR::ParameterDescriptor& desc);
|
||||
|
||||
bool base_event_handler (GdkEvent*);
|
||||
bool event_handler (GdkEvent*);
|
||||
};
|
||||
|
||||
|
@ -393,6 +393,12 @@ MidiCueEditor::current_page_samples() const
|
||||
return (samplecnt_t) _visible_canvas_width* samples_per_pixel;
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item* item, ControlPoint* cp)
|
||||
{
|
||||
return typed_event (item, event, ControlPointItem);
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::canvas_note_event (GdkEvent* event, ArdourCanvas::Item* item)
|
||||
{
|
||||
@ -518,6 +524,11 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
|
||||
}
|
||||
return true;
|
||||
|
||||
case ControlPointItem:
|
||||
_drags->set (new ControlPointDrag (*this, item), event);
|
||||
return true;
|
||||
break;
|
||||
|
||||
case VelocityItem:
|
||||
_drags->set (new LollipopDrag (*this, item), event);
|
||||
return true;
|
||||
@ -528,6 +539,17 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
|
||||
return true;
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
_drags->set (new AutomationDrawDrag (*this, nullptr, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
|
||||
return true;
|
||||
break;
|
||||
|
||||
case AutomationLineItem: {
|
||||
ARDOUR::SelectionOperation op = ArdourKeyboard::selection_type (event->button.state);
|
||||
select_automation_line (&event->button, item, op);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -604,18 +626,6 @@ MidiCueEditor::motion_handler (ArdourCanvas::Item*, GdkEvent* event, bool from_a
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::enter_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::leave_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::key_press_handler (ArdourCanvas::Item*, GdkEvent* ev, ItemType)
|
||||
{
|
||||
@ -1455,3 +1465,165 @@ MidiCueEditor::escape ()
|
||||
|
||||
view->clear_note_selection ();
|
||||
}
|
||||
Gdk::Cursor*
|
||||
MidiCueEditor::which_track_cursor () const
|
||||
{
|
||||
return _cursors->grabber;
|
||||
}
|
||||
|
||||
Gdk::Cursor*
|
||||
MidiCueEditor::which_mode_cursor () const
|
||||
{
|
||||
Gdk::Cursor* mode_cursor = MouseCursors::invalid_cursor ();
|
||||
|
||||
switch (mouse_mode) {
|
||||
case Editing::MouseContent:
|
||||
/* don't use mode cursor, pick a grabber cursor based on the item */
|
||||
break;
|
||||
|
||||
case Editing::MouseDraw:
|
||||
mode_cursor = _cursors->midi_pencil;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return mode_cursor;
|
||||
}
|
||||
|
||||
Gdk::Cursor*
|
||||
MidiCueEditor::which_trim_cursor (bool left_side) const
|
||||
{
|
||||
abort ();
|
||||
/*NOTREACHED*/
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Gdk::Cursor*
|
||||
MidiCueEditor::which_canvas_cursor (ItemType type) const
|
||||
{
|
||||
Gdk::Cursor* cursor = which_mode_cursor ();
|
||||
|
||||
if (mouse_mode == Editing::MouseContent) {
|
||||
|
||||
/* find correct cursor to use in object/smart mode */
|
||||
switch (type) {
|
||||
case AutomationTrackItem:
|
||||
cursor = which_track_cursor ();
|
||||
break;
|
||||
case PlayheadCursorItem:
|
||||
cursor = _cursors->grabber;
|
||||
break;
|
||||
case SelectionItem:
|
||||
cursor = _cursors->selector;
|
||||
break;
|
||||
case ControlPointItem:
|
||||
cursor = _cursors->fader;
|
||||
break;
|
||||
case GainLineItem:
|
||||
cursor = _cursors->cross_hair;
|
||||
break;
|
||||
case AutomationLineItem:
|
||||
cursor = _cursors->cross_hair;
|
||||
break;
|
||||
case StartSelectionTrimItem:
|
||||
cursor = _cursors->left_side_trim;
|
||||
break;
|
||||
case EndSelectionTrimItem:
|
||||
cursor = _cursors->right_side_trim;
|
||||
break;
|
||||
case NoteItem:
|
||||
cursor = _cursors->grabber_note;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (mouse_mode == Editing::MouseDraw) {
|
||||
|
||||
/* ControlPointItem is not really specific to region gain mode
|
||||
but it is the same cursor so don't worry about this for now.
|
||||
The result is that we'll see the fader cursor if we enter
|
||||
non-region-gain-line control points while in MouseDraw
|
||||
mode, even though we can't edit them in this mode.
|
||||
*/
|
||||
|
||||
switch (type) {
|
||||
case ControlPointItem:
|
||||
cursor = _cursors->fader;
|
||||
break;
|
||||
case NoteItem:
|
||||
cursor = _cursors->grabber_note;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::enter_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_type)
|
||||
{
|
||||
AutomationLine* al;
|
||||
|
||||
choose_canvas_cursor_on_entry (item_type);
|
||||
|
||||
switch (item_type) {
|
||||
case AutomationTrackItem:
|
||||
/* item is the base rectangle */
|
||||
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
|
||||
al->track_entered ();
|
||||
break;
|
||||
|
||||
case AutomationLineItem:
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
|
||||
if (line) {
|
||||
line->set_outline_color (UIConfiguration::instance().color ("entered automation line"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::leave_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_type)
|
||||
{
|
||||
AutomationLine* al;
|
||||
|
||||
if (!_enter_stack.empty()) {
|
||||
_enter_stack.pop_back();
|
||||
}
|
||||
|
||||
switch (item_type) {
|
||||
case ControlPointItem:
|
||||
_verbose_cursor->hide ();
|
||||
break;
|
||||
|
||||
case AutomationLineItem:
|
||||
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
|
||||
{
|
||||
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
||||
if (line) {
|
||||
line->set_outline_color (al->get_line_color());
|
||||
}
|
||||
}
|
||||
if (ev->crossing.detail != GDK_NOTIFY_INFERIOR) {
|
||||
al->track_exited ();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ class MidiCueEditor : public CueEditor
|
||||
bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*);
|
||||
bool canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item*);
|
||||
bool canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item*);
|
||||
bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*);
|
||||
|
||||
int32_t get_grid_beat_divisions (Editing::GridType gt) const { return 1; }
|
||||
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; }
|
||||
@ -98,6 +99,11 @@ class MidiCueEditor : public CueEditor
|
||||
|
||||
void midi_action (void (MidiView::*method)());
|
||||
|
||||
Gdk::Cursor* which_track_cursor () const;
|
||||
Gdk::Cursor* which_mode_cursor () const;
|
||||
Gdk::Cursor* which_trim_cursor (bool left_side) const;
|
||||
Gdk::Cursor* which_canvas_cursor (ItemType type) const;
|
||||
|
||||
protected:
|
||||
void register_actions ();
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "midi_cue_view.h"
|
||||
#include "midi_cue_velocity.h"
|
||||
#include "note.h"
|
||||
#include "ui_config.h"
|
||||
#include "velocity_display.h"
|
||||
|
||||
#include "pbd/i18n.h"
|
||||
@ -70,6 +71,7 @@ MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
|
||||
|
||||
automation_group = new ArdourCanvas::Rectangle (&parent);
|
||||
CANVAS_DEBUG_NAME (automation_group, "cue automation group");
|
||||
automation_group->set_fill_color (UIConfiguration::instance().color ("midi automation track fill"));
|
||||
|
||||
velocity_base = new ArdourCanvas::Rectangle (&parent);
|
||||
CANVAS_DEBUG_NAME (velocity_base, "cue velocity base");
|
||||
@ -275,7 +277,6 @@ MidiCueView::show_automation (Evoral::Parameter const & param)
|
||||
std::shared_ptr<AutomationControl> ac = std::dynamic_pointer_cast<AutomationControl> (control);
|
||||
|
||||
if (ac) {
|
||||
std::cerr << "found control, list contains " << ac->alist()->size() << std::endl;
|
||||
automation_line = new MidiCueAutomationLine ("whatevs",
|
||||
_editing_context,
|
||||
*automation_group,
|
||||
|
@ -1753,8 +1753,6 @@ MidiView::add_note(const std::shared_ptr<NoteType> note, bool visible)
|
||||
event = 0;
|
||||
}
|
||||
|
||||
std::cerr << "add note, event " << event << std::endl;
|
||||
|
||||
if (event) {
|
||||
ghost_add_note (event);
|
||||
|
||||
|
@ -2606,7 +2606,7 @@ RouteTimeAxisView::automation_child(Evoral::Parameter param, PBD::ID ctrl_id)
|
||||
return std::shared_ptr<AutomationTimeAxisView>();
|
||||
}
|
||||
|
||||
std::shared_ptr<AutomationLine>
|
||||
std::shared_ptr<AutomationLineBase>
|
||||
RouteTimeAxisView::automation_child_by_alist_id (PBD::ID alist_id)
|
||||
{
|
||||
for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
|
||||
@ -2615,10 +2615,9 @@ RouteTimeAxisView::automation_child_by_alist_id (PBD::ID alist_id)
|
||||
if (!atv) {
|
||||
continue;
|
||||
}
|
||||
list<std::shared_ptr<AutomationLine> > lines = atv->lines();
|
||||
for (list<std::shared_ptr<AutomationLine> >::const_iterator li = lines.begin(); li != lines.end(); ++li) {
|
||||
if ((*li)->the_list()->id() == alist_id) {
|
||||
return *li;
|
||||
for (auto & line : atv->lines()) {
|
||||
if (line->the_list()->id() == alist_id) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ protected:
|
||||
void add_processor_automation_curve (std::shared_ptr<ARDOUR::Processor> r, Evoral::Parameter);
|
||||
void add_existing_processor_automation_curves (std::weak_ptr<ARDOUR::Processor>);
|
||||
|
||||
std::shared_ptr<AutomationLine> automation_child_by_alist_id (PBD::ID);
|
||||
std::shared_ptr<AutomationLineBase> automation_child_by_alist_id (PBD::ID);
|
||||
|
||||
void reset_processor_automation_curves ();
|
||||
|
||||
|
@ -1315,7 +1315,7 @@ Selection::set_state (XMLNode const & node, int)
|
||||
vector <ControlPoint *> cps;
|
||||
|
||||
if (stv) {
|
||||
std::shared_ptr<AutomationLine> li = stv->automation_child_by_alist_id (alist_id);
|
||||
std::shared_ptr<AutomationLineBase> li = stv->automation_child_by_alist_id (alist_id);
|
||||
if (li) {
|
||||
ControlPoint* cp = li->nth(view_index);
|
||||
if (cp) {
|
||||
|
@ -192,15 +192,14 @@ StripableTimeAxisView::automation_child(Evoral::Parameter param, PBD::ID)
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<AutomationLine>
|
||||
std::shared_ptr<AutomationLineBase>
|
||||
StripableTimeAxisView::automation_child_by_alist_id (PBD::ID alist_id)
|
||||
{
|
||||
for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
|
||||
std::shared_ptr<AutomationTimeAxisView> atv (i->second);
|
||||
std::list<std::shared_ptr<AutomationLine> > lines = atv->lines();
|
||||
for (std::list<std::shared_ptr<AutomationLine> >::const_iterator li = lines.begin(); li != lines.end(); ++li) {
|
||||
if ((*li)->the_list()->id() == alist_id) {
|
||||
return *li;
|
||||
for (auto & line : atv->lines()) {
|
||||
if (line->the_list()->id() == alist_id) {
|
||||
return line;;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
virtual void create_automation_child (const Evoral::Parameter& param, bool show) = 0;
|
||||
virtual std::shared_ptr<AutomationTimeAxisView> automation_child (Evoral::Parameter param, PBD::ID ctrl_id = PBD::ID(0));
|
||||
|
||||
virtual std::shared_ptr<AutomationLine> automation_child_by_alist_id (PBD::ID);
|
||||
virtual std::shared_ptr<AutomationLineBase> automation_child_by_alist_id (PBD::ID);
|
||||
|
||||
void request_redraw ();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user