mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 23:05:04 +01:00
move note drag & note resize mouse handling up into the Drag/Editor infrastructure/level
git-svn-id: svn://localhost/ardour2/branches/3.0@5641 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
539c8361de
commit
1bf79fa885
13 changed files with 283 additions and 258 deletions
|
|
@ -218,18 +218,9 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiStreamView *streamview = _region.midi_stream_view();
|
|
||||||
static uint8_t drag_delta_note = 0;
|
|
||||||
static double drag_delta_x = 0;
|
|
||||||
static double last_x, last_y;
|
|
||||||
double event_x, event_y, dx, dy;
|
|
||||||
bool select_mod;
|
|
||||||
|
|
||||||
switch (ev->type) {
|
switch (ev->type) {
|
||||||
case GDK_ENTER_NOTIFY:
|
case GDK_ENTER_NOTIFY:
|
||||||
_region.note_entered(this);
|
_region.note_entered(this);
|
||||||
//_item->grab_focus();
|
|
||||||
//show_velocity();
|
|
||||||
//Keyboard::magic_widget_grab_focus();
|
//Keyboard::magic_widget_grab_focus();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -239,118 +230,20 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
|
||||||
if (!selected()) {
|
if (!selected()) {
|
||||||
hide_velocity();
|
hide_velocity();
|
||||||
}
|
}
|
||||||
//_region.get_canvas_group()->grab_focus();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
if (ev->button.button == 1) {
|
if (ev->button.button == 3) {
|
||||||
_state = Pressed;
|
|
||||||
} else if (ev->button.button == 3) {
|
|
||||||
show_channel_selector();
|
show_channel_selector();
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case GDK_MOTION_NOTIFY:
|
|
||||||
event_x = ev->motion.x;
|
|
||||||
event_y = ev->motion.y;
|
|
||||||
|
|
||||||
switch (_state) {
|
|
||||||
case Pressed: // Drag begin
|
|
||||||
if (editor.current_mouse_mode() == Editing::MouseObject && _region.mouse_state() != MidiRegionView::SelectTouchDragging) {
|
|
||||||
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
|
||||||
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
|
|
||||||
_state = Dragging;
|
|
||||||
_item->property_parent().get_value()->w2i(event_x, event_y);
|
|
||||||
event_x = _region.snap_to_pixel(event_x);
|
|
||||||
last_x = event_x;
|
|
||||||
last_y = event_y;
|
|
||||||
drag_delta_x = 0;
|
|
||||||
drag_delta_note = 0;
|
|
||||||
_region.note_selected(this, true);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Dragging: // Drag motion
|
|
||||||
if (ev->motion.is_hint) {
|
|
||||||
int t_x;
|
|
||||||
int t_y;
|
|
||||||
GdkModifierType state;
|
|
||||||
gdk_window_get_pointer(ev->motion.window, &t_x, &t_y, &state);
|
|
||||||
event_x = t_x;
|
|
||||||
event_y = t_y;
|
|
||||||
}
|
|
||||||
_item->property_parent().get_value()->w2i(event_x, event_y);
|
|
||||||
|
|
||||||
event_x = _region.snap_to_pixel(event_x);
|
|
||||||
|
|
||||||
dx = event_x - last_x;
|
|
||||||
dy = event_y - last_y;
|
|
||||||
last_x = event_x;
|
|
||||||
|
|
||||||
drag_delta_x += dx;
|
|
||||||
|
|
||||||
// Snap to note rows
|
|
||||||
if (abs(dy) < streamview->note_height()) {
|
|
||||||
dy = 0.0;
|
|
||||||
} else {
|
|
||||||
int8_t this_delta_note;
|
|
||||||
if (dy > 0) {
|
|
||||||
this_delta_note = (int8_t)ceil(dy / streamview->note_height() / 2.0);
|
|
||||||
} else {
|
|
||||||
this_delta_note = (int8_t)floor(dy / streamview->note_height() / 2.0);
|
|
||||||
}
|
|
||||||
drag_delta_note -= this_delta_note;
|
|
||||||
dy = streamview->note_height() * this_delta_note;
|
|
||||||
last_y = last_y + dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
_region.move_selection(dx, dy);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
select_mod = (ev->motion.state & (Keyboard::PrimaryModifier | Keyboard::SecondaryModifier));
|
|
||||||
event_x = ev->button.x;
|
|
||||||
event_y = ev->button.y;
|
|
||||||
_item->property_parent().get_value()->w2i(event_x, event_y);
|
|
||||||
|
|
||||||
if (ev->button.button == 3) {
|
if (ev->button.button == 3) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
switch (_state) {
|
|
||||||
case Pressed: // Clicked
|
|
||||||
if (editor.current_mouse_mode() == Editing::MouseRange) {
|
|
||||||
_state = None;
|
|
||||||
if (_selected) {
|
|
||||||
_region.note_deselected(this, select_mod);
|
|
||||||
} else {
|
|
||||||
bool extend = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::TertiaryModifier);
|
|
||||||
bool add = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier);
|
|
||||||
|
|
||||||
if (!extend && !add && _region.selection_size() > 1) {
|
|
||||||
_region.unique_select(this);
|
|
||||||
} else {
|
|
||||||
_region.note_selected (this, (extend ? true : add), extend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case Dragging: // Dropped
|
|
||||||
_item->ungrab(ev->button.time);
|
|
||||||
_state = None;
|
|
||||||
if (_note) {
|
|
||||||
_region.note_dropped(this, drag_delta_x, drag_delta_note);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ public:
|
||||||
virtual double y2() = 0;
|
virtual double y2() = 0;
|
||||||
|
|
||||||
const boost::shared_ptr<NoteType> note() const { return _note; }
|
const boost::shared_ptr<NoteType> note() const { return _note; }
|
||||||
|
MidiRegionView& region_view() const { return _region; }
|
||||||
|
|
||||||
inline static uint32_t meter_style_fill_color(uint8_t vel) {
|
inline static uint32_t meter_style_fill_color(uint8_t vel) {
|
||||||
if (vel < 64) {
|
if (vel < 64) {
|
||||||
|
|
|
||||||
|
|
@ -11,84 +11,10 @@ namespace Canvas {
|
||||||
bool
|
bool
|
||||||
CanvasNote::on_event(GdkEvent* ev)
|
CanvasNote::on_event(GdkEvent* ev)
|
||||||
{
|
{
|
||||||
PublicEditor& editor (_region.get_trackview().editor());
|
if (!_region.get_trackview().editor().canvas_note_event (ev, this)) {
|
||||||
|
return CanvasNoteEvent::on_event (ev);
|
||||||
if (!editor.internal_editing()) {
|
} else {
|
||||||
return false;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
double event_x;
|
|
||||||
static double middle_point, last_x;
|
|
||||||
Gdk::Cursor cursor;
|
|
||||||
static NoteEnd note_end;
|
|
||||||
|
|
||||||
switch (ev->type) {
|
|
||||||
case GDK_BUTTON_PRESS:
|
|
||||||
if (ev->button.button == 2 ||
|
|
||||||
(ev->button.button == 1 && editor.current_mouse_mode() == Editing::MouseTimeFX)) {
|
|
||||||
double region_start = _region.get_position_pixels();
|
|
||||||
event_x = ev->button.x;
|
|
||||||
middle_point = region_start + x1() + (x2() - x1()) / 2.0L;
|
|
||||||
|
|
||||||
if (event_x <= middle_point) {
|
|
||||||
cursor = Gdk::Cursor(Gdk::LEFT_SIDE);
|
|
||||||
note_end = NOTE_ON;
|
|
||||||
} else {
|
|
||||||
cursor = Gdk::Cursor(Gdk::RIGHT_SIDE);
|
|
||||||
note_end = NOTE_OFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, cursor, ev->motion.time);
|
|
||||||
|
|
||||||
if (_region.mouse_state() == MidiRegionView::SelectTouchDragging) {
|
|
||||||
_note_state = AbsoluteResize;
|
|
||||||
} else {
|
|
||||||
_note_state = RelativeResize;
|
|
||||||
}
|
|
||||||
|
|
||||||
_region.note_selected(this, true);
|
|
||||||
_region.begin_resizing(note_end);
|
|
||||||
last_x = event_x;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GDK_MOTION_NOTIFY:
|
|
||||||
event_x = ev->motion.x;
|
|
||||||
|
|
||||||
if (_note_state == RelativeResize) {
|
|
||||||
_region.update_resizing(note_end, event_x - last_x, true);
|
|
||||||
last_x = event_x;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_note_state == AbsoluteResize) {
|
|
||||||
_region.update_resizing(note_end, event_x, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GDK_BUTTON_RELEASE:
|
|
||||||
event_x = ev->button.x;
|
|
||||||
|
|
||||||
switch (_note_state) {
|
|
||||||
case RelativeResize: // Clicked
|
|
||||||
_item->ungrab(ev->button.time);
|
|
||||||
_region.commit_resizing(note_end, event_x, true);
|
|
||||||
_note_state = None;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case AbsoluteResize: // Clicked
|
|
||||||
_item->ungrab(ev->button.time);
|
|
||||||
_region.commit_resizing(note_end, event_x, false);
|
|
||||||
_note_state = None;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CanvasNoteEvent::on_event(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CanvasNoteEvent::on_event(ev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace Canvas {
|
||||||
|
|
||||||
class CanvasNote : public SimpleRect, public CanvasNoteEvent {
|
class CanvasNote : public SimpleRect, public CanvasNoteEvent {
|
||||||
public:
|
public:
|
||||||
typedef Evoral::Note<double> NoteType;
|
typedef Evoral::Note<Evoral::MusicalTime> NoteType;
|
||||||
|
|
||||||
double x1() { return property_x1(); }
|
double x1() { return property_x1(); }
|
||||||
double y1() { return property_y1(); }
|
double y1() { return property_y1(); }
|
||||||
|
|
@ -46,27 +46,12 @@ public:
|
||||||
|
|
||||||
bool on_event(GdkEvent* ev);
|
bool on_event(GdkEvent* ev);
|
||||||
|
|
||||||
enum NoteEnd {
|
CanvasNote (MidiRegionView& region,
|
||||||
NOTE_ON,
|
Group& group,
|
||||||
NOTE_OFF
|
const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>())
|
||||||
};
|
: SimpleRect(group), CanvasNoteEvent(region, this, note)
|
||||||
|
|
||||||
enum NoteState {
|
|
||||||
None,
|
|
||||||
RelativeResize,
|
|
||||||
AbsoluteResize
|
|
||||||
};
|
|
||||||
|
|
||||||
CanvasNote(
|
|
||||||
MidiRegionView& region,
|
|
||||||
Group& group,
|
|
||||||
const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>())
|
|
||||||
: SimpleRect(group), CanvasNoteEvent(region, this, note), _note_state(None)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
NoteState _note_state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Gnome
|
} // namespace Gnome
|
||||||
|
|
|
||||||
|
|
@ -1370,6 +1370,7 @@ public:
|
||||||
bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*);
|
bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*);
|
||||||
bool canvas_meter_marker_event (GdkEvent* event,ArdourCanvas::Item*, MeterMarker*);
|
bool canvas_meter_marker_event (GdkEvent* event,ArdourCanvas::Item*, MeterMarker*);
|
||||||
bool canvas_automation_track_event(GdkEvent* event, ArdourCanvas::Item*, AutomationTimeAxisView*) ;
|
bool canvas_automation_track_event(GdkEvent* event, ArdourCanvas::Item*, AutomationTimeAxisView*) ;
|
||||||
|
bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*);
|
||||||
|
|
||||||
bool canvas_tempo_bar_event (GdkEvent* event, ArdourCanvas::Item*);
|
bool canvas_tempo_bar_event (GdkEvent* event, ArdourCanvas::Item*);
|
||||||
bool canvas_meter_bar_event (GdkEvent* event, ArdourCanvas::Item*);
|
bool canvas_meter_bar_event (GdkEvent* event, ArdourCanvas::Item*);
|
||||||
|
|
|
||||||
|
|
@ -983,6 +983,16 @@ Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
|
||||||
return typed_event (item, event, NoItem);
|
return typed_event (item, event, NoItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
|
||||||
|
{
|
||||||
|
if (!internal_editing()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typed_event (item, event, NoteItem);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, int x, int y, guint /*time*/)
|
Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, int x, int y, guint /*time*/)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include "editor_drag.h"
|
#include "editor_drag.h"
|
||||||
#include "audio_time_axis.h"
|
#include "audio_time_axis.h"
|
||||||
#include "midi_time_axis.h"
|
#include "midi_time_axis.h"
|
||||||
|
#include "canvas-note.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
@ -1379,6 +1380,58 @@ RegionCreateDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
|
||||||
|
: Drag (e, i)
|
||||||
|
, region (0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
|
||||||
|
{
|
||||||
|
Gdk::Cursor cursor;
|
||||||
|
ArdourCanvas::CanvasNote* cnote = dynamic_cast<ArdourCanvas::CanvasNote*>(_item);
|
||||||
|
|
||||||
|
Drag::start_grab (event);
|
||||||
|
|
||||||
|
region = &cnote->region_view();
|
||||||
|
|
||||||
|
double region_start = region->get_position_pixels();
|
||||||
|
double middle_point = region_start + cnote->x1() + (cnote->x2() - cnote->x1()) / 2.0L;
|
||||||
|
|
||||||
|
if (_grab_x <= middle_point) {
|
||||||
|
cursor = Gdk::Cursor(Gdk::LEFT_SIDE);
|
||||||
|
at_front = true;
|
||||||
|
} else {
|
||||||
|
cursor = Gdk::Cursor(Gdk::RIGHT_SIDE);
|
||||||
|
at_front = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, cursor, event->motion.time);
|
||||||
|
|
||||||
|
if (event->motion.state & Keyboard::PrimaryModifier) {
|
||||||
|
relative = false;
|
||||||
|
} else {
|
||||||
|
relative = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
region->note_selected (cnote, true);
|
||||||
|
region->begin_resizing (at_front);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NoteResizeDrag::motion (GdkEvent* /*event*/, bool first_move)
|
||||||
|
{
|
||||||
|
region->update_resizing (at_front, _current_pointer_x - _grab_x, relative);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NoteResizeDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||||
|
{
|
||||||
|
region->commit_resizing (at_front, _current_pointer_x - _grab_x, relative);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RegionGainDrag::motion (GdkEvent* /*event*/, bool)
|
RegionGainDrag::motion (GdkEvent* /*event*/, bool)
|
||||||
{
|
{
|
||||||
|
|
@ -3287,3 +3340,100 @@ MouseZoomDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||||
|
|
||||||
_editor->zoom_rect->hide();
|
_editor->zoom_rect->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NoteDrag::NoteDrag (Editor* e, ArdourCanvas::Item* i)
|
||||||
|
: Drag (e, i)
|
||||||
|
{
|
||||||
|
ArdourCanvas::CanvasNote* cnote = dynamic_cast<ArdourCanvas::CanvasNote*>(_item);
|
||||||
|
region = &cnote->region_view();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
|
||||||
|
{
|
||||||
|
Drag::start_grab (event);
|
||||||
|
|
||||||
|
drag_delta_x = 0;
|
||||||
|
drag_delta_note = 0;
|
||||||
|
|
||||||
|
double event_x;
|
||||||
|
double event_y;
|
||||||
|
|
||||||
|
event_x = _current_pointer_x;
|
||||||
|
event_y = _current_pointer_y;
|
||||||
|
|
||||||
|
_item->property_parent().get_value()->w2i(event_x, event_y);
|
||||||
|
|
||||||
|
last_x = region->snap_to_pixel(event_x);
|
||||||
|
last_y = event_y;
|
||||||
|
|
||||||
|
ArdourCanvas::CanvasNote* cnote = dynamic_cast<ArdourCanvas::CanvasNote*>(_item);
|
||||||
|
region->note_selected (cnote, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NoteDrag::motion (GdkEvent* ev, bool)
|
||||||
|
{
|
||||||
|
MidiStreamView* streamview = region->midi_stream_view();
|
||||||
|
double event_x;
|
||||||
|
double event_y;
|
||||||
|
|
||||||
|
event_x = _current_pointer_x;
|
||||||
|
event_y = _current_pointer_y;
|
||||||
|
|
||||||
|
_item->property_parent().get_value()->w2i(event_x, event_y);
|
||||||
|
|
||||||
|
event_x = region->snap_to_pixel(event_x);
|
||||||
|
|
||||||
|
double dx = event_x - last_x;
|
||||||
|
double dy = event_y - last_y;
|
||||||
|
last_x = event_x;
|
||||||
|
|
||||||
|
drag_delta_x += dx;
|
||||||
|
|
||||||
|
// Snap to note rows
|
||||||
|
|
||||||
|
if (abs (dy) < streamview->note_height()) {
|
||||||
|
dy = 0.0;
|
||||||
|
} else {
|
||||||
|
int8_t this_delta_note;
|
||||||
|
if (dy > 0) {
|
||||||
|
this_delta_note = (int8_t)ceil(dy / streamview->note_height() / 2.0);
|
||||||
|
} else {
|
||||||
|
this_delta_note = (int8_t)floor(dy / streamview->note_height() / 2.0);
|
||||||
|
}
|
||||||
|
drag_delta_note -= this_delta_note;
|
||||||
|
dy = streamview->note_height() * this_delta_note;
|
||||||
|
last_y = last_y + dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
region->move_selection (dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NoteDrag::finished (GdkEvent* ev, bool moved)
|
||||||
|
{
|
||||||
|
ArdourCanvas::CanvasNote* cnote = dynamic_cast<ArdourCanvas::CanvasNote*>(_item);
|
||||||
|
|
||||||
|
if (!moved) {
|
||||||
|
if (_editor->current_mouse_mode() == Editing::MouseObject) {
|
||||||
|
|
||||||
|
bool select_mod = (ev->motion.state & (Keyboard::PrimaryModifier | Keyboard::SecondaryModifier));
|
||||||
|
|
||||||
|
if (cnote->selected()) {
|
||||||
|
region->note_deselected (cnote, select_mod);
|
||||||
|
} else {
|
||||||
|
bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
|
||||||
|
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
|
||||||
|
|
||||||
|
if (!extend && !add && region->selection_size() > 1) {
|
||||||
|
region->unique_select(cnote);
|
||||||
|
} else {
|
||||||
|
region->note_selected (cnote, (extend ? true : add), extend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
region->note_dropped (cnote, drag_delta_x, drag_delta_note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,39 @@ private:
|
||||||
TimeAxisView* _dest_trackview;
|
TimeAxisView* _dest_trackview;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Drags to resize MIDI notes */
|
||||||
|
class NoteResizeDrag : public Drag
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NoteResizeDrag (Editor *, ArdourCanvas::Item *);
|
||||||
|
|
||||||
|
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
|
||||||
|
void motion (GdkEvent *, bool);
|
||||||
|
void finished (GdkEvent *, bool);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MidiRegionView* region;
|
||||||
|
bool relative;
|
||||||
|
bool at_front;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NoteDrag : public Drag
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NoteDrag (Editor*, ArdourCanvas::Item*);
|
||||||
|
|
||||||
|
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
|
||||||
|
void motion (GdkEvent *, bool);
|
||||||
|
void finished (GdkEvent *, bool);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MidiRegionView* region;
|
||||||
|
double last_x;
|
||||||
|
double last_y;
|
||||||
|
double drag_delta_x;
|
||||||
|
double drag_delta_note;
|
||||||
|
};
|
||||||
|
|
||||||
/** Drag of region gain */
|
/** Drag of region gain */
|
||||||
class RegionGainDrag : public Drag
|
class RegionGainDrag : public Drag
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ enum ItemType {
|
||||||
FadeInHandleItem,
|
FadeInHandleItem,
|
||||||
FadeOutItem,
|
FadeOutItem,
|
||||||
FadeOutHandleItem,
|
FadeOutHandleItem,
|
||||||
|
NoteItem,
|
||||||
|
|
||||||
#ifdef WITH_CMT
|
#ifdef WITH_CMT
|
||||||
MarkerViewItem,
|
MarkerViewItem,
|
||||||
MarkerTimeAxisItem,
|
MarkerTimeAxisItem,
|
||||||
|
|
|
||||||
|
|
@ -605,6 +605,22 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||||
_drag = new RegionCreateDrag (this, item, clicked_axisview);
|
_drag = new RegionCreateDrag (this, item, clicked_axisview);
|
||||||
_drag->start_grab (event);
|
_drag->start_grab (event);
|
||||||
return true;
|
return true;
|
||||||
|
case NoteItem:
|
||||||
|
/* Note: we don't get here if not in internal_editing() mode */
|
||||||
|
if (mouse_mode == MouseTimeFX) {
|
||||||
|
assert (_drag == 0);
|
||||||
|
_drag = new NoteResizeDrag (this, item);
|
||||||
|
_drag->start_grab (event);
|
||||||
|
return true;
|
||||||
|
} else if (mouse_mode == MouseObject) {
|
||||||
|
assert (_drag == 0);
|
||||||
|
_drag = new NoteDrag (this, item);
|
||||||
|
_drag->start_grab (event);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,7 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
||||||
|
|
||||||
// Select drag start
|
// Select drag start
|
||||||
if (_pressed_button == 1 && editor.current_mouse_mode() == MouseObject) {
|
if (_pressed_button == 1 && editor.current_mouse_mode() == MouseObject) {
|
||||||
|
cerr << "MRV start select grab\n";
|
||||||
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
||||||
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
|
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
|
||||||
last_x = event_x;
|
last_x = event_x;
|
||||||
|
|
@ -376,6 +377,7 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
||||||
|
|
||||||
// Add note drag start
|
// Add note drag start
|
||||||
} else if (editor.current_mouse_mode() == MouseRange) {
|
} else if (editor.current_mouse_mode() == MouseRange) {
|
||||||
|
cerr << "MRV start note grab\n";
|
||||||
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
||||||
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
|
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
|
||||||
last_x = event_x;
|
last_x = event_x;
|
||||||
|
|
@ -1680,7 +1682,7 @@ MidiRegionView::frames_to_beats(nframes64_t frames) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::begin_resizing(CanvasNote::NoteEnd note_end)
|
MidiRegionView::begin_resizing(bool at_front)
|
||||||
{
|
{
|
||||||
_resize_data.clear();
|
_resize_data.clear();
|
||||||
|
|
||||||
|
|
@ -1714,37 +1716,37 @@ MidiRegionView::begin_resizing(CanvasNote::NoteEnd note_end)
|
||||||
ARDOUR_UI::config()->canvasvar_MidiNoteSelected.get());
|
ARDOUR_UI::config()->canvasvar_MidiNoteSelected.get());
|
||||||
|
|
||||||
resize_data->resize_rect = resize_rect;
|
resize_data->resize_rect = resize_rect;
|
||||||
|
|
||||||
if (note_end == CanvasNote::NOTE_ON) {
|
|
||||||
resize_data->current_x = note->x1();
|
|
||||||
} else { // NOTE_OFF
|
|
||||||
resize_data->current_x = note->x2();
|
|
||||||
}
|
|
||||||
|
|
||||||
_resize_data.push_back(resize_data);
|
_resize_data.push_back(resize_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double x, bool relative)
|
MidiRegionView::update_resizing (bool at_front, double delta_x, bool relative)
|
||||||
{
|
{
|
||||||
for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
|
for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
|
||||||
SimpleRect* resize_rect = (*i)->resize_rect;
|
SimpleRect* resize_rect = (*i)->resize_rect;
|
||||||
CanvasNote* canvas_note = (*i)->canvas_note;
|
CanvasNote* canvas_note = (*i)->canvas_note;
|
||||||
|
|
||||||
const double region_start = get_position_pixels();
|
const double region_start = get_position_pixels();
|
||||||
|
double current_x;
|
||||||
|
|
||||||
if (relative) {
|
if (at_front) {
|
||||||
(*i)->current_x = (*i)->current_x + x;
|
if (relative) {
|
||||||
|
current_x = canvas_note->x1() + delta_x;
|
||||||
|
} else {
|
||||||
|
// x is in track relative, transform it to region relative
|
||||||
|
current_x = delta_x - region_start;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// x is in track relative, transform it to region relative
|
if (relative) {
|
||||||
(*i)->current_x = x - region_start;
|
current_x = canvas_note->x2() + delta_x;
|
||||||
|
} else {
|
||||||
|
// x is in track relative, transform it to region relative
|
||||||
|
current_x = delta_x - region_start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double current_x = (*i)->current_x;
|
if (at_front) {
|
||||||
|
|
||||||
if (note_end == CanvasNote::NOTE_ON) {
|
|
||||||
resize_rect->property_x1() = snap_to_pixel(current_x);
|
resize_rect->property_x1() = snap_to_pixel(current_x);
|
||||||
resize_rect->property_x2() = canvas_note->x2();
|
resize_rect->property_x2() = canvas_note->x2();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1755,40 +1757,47 @@ MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double x, bool rel
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bool relative)
|
MidiRegionView::commit_resizing (bool at_front, double delta_x, bool relative)
|
||||||
{
|
{
|
||||||
start_delta_command(_("resize notes"));
|
start_diff_command(_("resize notes"));
|
||||||
|
|
||||||
for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
|
for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
|
||||||
CanvasNote* canvas_note = (*i)->canvas_note;
|
CanvasNote* canvas_note = (*i)->canvas_note;
|
||||||
SimpleRect* resize_rect = (*i)->resize_rect;
|
SimpleRect* resize_rect = (*i)->resize_rect;
|
||||||
double current_x = (*i)->current_x;
|
const double region_start = get_position_pixels();
|
||||||
const double position = get_position_pixels();
|
double current_x;
|
||||||
|
|
||||||
if (!relative) {
|
if (at_front) {
|
||||||
// event_x is in track relative, transform it to region relative
|
if (relative) {
|
||||||
current_x = event_x - position;
|
current_x = canvas_note->x1() + delta_x;
|
||||||
|
} else {
|
||||||
|
// x is in track relative, transform it to region relative
|
||||||
|
current_x = delta_x - region_start;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (relative) {
|
||||||
|
current_x = canvas_note->x2() + delta_x;
|
||||||
|
} else {
|
||||||
|
// x is in track relative, transform it to region relative
|
||||||
|
current_x = delta_x - region_start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// because snapping works on world coordinates we have to transform current_x
|
|
||||||
// to world coordinates before snapping and transform it back afterwards
|
|
||||||
nframes64_t current_frame = snap_pixel_to_frame(current_x);
|
|
||||||
// transform to region start relative
|
|
||||||
current_frame += _region->start();
|
|
||||||
|
|
||||||
const boost::shared_ptr<NoteType> copy(new NoteType(*(canvas_note->note().get())));
|
current_x = snap_pixel_to_frame (current_x);
|
||||||
|
current_x = frames_to_beats (current_x);
|
||||||
|
|
||||||
// resize beginning of note
|
if (at_front && current_x < canvas_note->note()->end_time()) {
|
||||||
if (note_end == CanvasNote::NOTE_ON && current_frame < copy->end_time()) {
|
|
||||||
delta_remove_note(canvas_note);
|
diff_add_change (canvas_note, MidiModel::DiffCommand::StartTime, current_x);
|
||||||
copy->on_event().time() = current_frame;
|
|
||||||
delta_add_note(copy, _selection.find(canvas_note) != _selection.end());
|
|
||||||
}
|
}
|
||||||
// resize end of note
|
|
||||||
if (note_end == CanvasNote::NOTE_OFF && current_frame > copy->time()) {
|
if (!at_front) {
|
||||||
delta_remove_note(canvas_note);
|
double len = current_x - canvas_note->note()->time();
|
||||||
copy->off_event().time() = current_frame;
|
|
||||||
delta_add_note(copy, _selection.find(canvas_note) != _selection.end());
|
if (len > 0) {
|
||||||
|
/* XXX convert to beats */
|
||||||
|
diff_add_change (canvas_note, MidiModel::DiffCommand::Length, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete resize_rect;
|
delete resize_rect;
|
||||||
|
|
@ -1796,7 +1805,7 @@ MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bo
|
||||||
}
|
}
|
||||||
|
|
||||||
_resize_data.clear();
|
_resize_data.clear();
|
||||||
apply_delta();
|
apply_diff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -201,24 +201,24 @@ class MidiRegionView : public RegionView
|
||||||
|
|
||||||
/** Begin resizing of some notes.
|
/** Begin resizing of some notes.
|
||||||
* Called by CanvasMidiNote when resizing starts.
|
* Called by CanvasMidiNote when resizing starts.
|
||||||
* @param note_end which end of the note, NOTE_ON or NOTE_OFF
|
* @param at_front which end of the note (true == note on, false == note off)
|
||||||
*/
|
*/
|
||||||
void begin_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end);
|
void begin_resizing(bool at_front);
|
||||||
|
|
||||||
/** Update resizing notes while user drags.
|
/** Update resizing notes while user drags.
|
||||||
* @param note_end which end of the note, NOTE_ON or NOTE_OFF
|
* @param at_front which end of the note (true == note on, false == note off)
|
||||||
* @param x the difference in mouse motion, ie the motion difference if relative=true
|
* @param x the difference in mouse motion, ie the motion difference if relative=true
|
||||||
* or the absolute mouse position (track-relative) if relative is false
|
* or the absolute mouse position (track-relative) if relative is false
|
||||||
* @param relative true if relative resizing is taking place, false if absolute resizing
|
* @param relative true if relative resizing is taking place, false if absolute resizing
|
||||||
*/
|
*/
|
||||||
void update_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double x, bool relative);
|
void update_resizing(bool at_front, double x, bool relative);
|
||||||
|
|
||||||
/** Finish resizing notes when the user releases the mouse button.
|
/** Finish resizing notes when the user releases the mouse button.
|
||||||
* @param note_end which end of the note, NOTE_ON or NOTE_OFF
|
* @param at_front which end of the note (true == note on, false == note off)
|
||||||
* @param event_x the absolute mouse position (track-relative)
|
* @param event_x the absolute mouse position (track-relative)
|
||||||
* @param relative true if relative resizing is taking place, false if absolute resizing
|
* @param relative true if relative resizing is taking place, false if absolute resizing
|
||||||
*/
|
*/
|
||||||
void commit_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double event_x, bool relative);
|
void commit_resizing(bool at_front, double event_x, bool relative);
|
||||||
|
|
||||||
/** Adjust the velocity on a note, and the selection if applicable.
|
/** Adjust the velocity on a note, and the selection if applicable.
|
||||||
* @param velocity the relative or absolute velocity
|
* @param velocity the relative or absolute velocity
|
||||||
|
|
@ -244,7 +244,6 @@ class MidiRegionView : public RegionView
|
||||||
struct NoteResizeData {
|
struct NoteResizeData {
|
||||||
ArdourCanvas::CanvasNote *canvas_note;
|
ArdourCanvas::CanvasNote *canvas_note;
|
||||||
ArdourCanvas::SimpleRect *resize_rect;
|
ArdourCanvas::SimpleRect *resize_rect;
|
||||||
double current_x;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Snap a region relative pixel coordinate to pixel units.
|
/** Snap a region relative pixel coordinate to pixel units.
|
||||||
|
|
|
||||||
|
|
@ -312,6 +312,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
|
||||||
virtual bool canvas_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
virtual bool canvas_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
||||||
virtual bool canvas_range_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
virtual bool canvas_range_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
||||||
virtual bool canvas_transport_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
virtual bool canvas_transport_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
||||||
|
virtual bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
|
||||||
|
|
||||||
#ifdef WITH_CMT
|
#ifdef WITH_CMT
|
||||||
virtual bool canvas_imageframe_item_view_event(GdkEvent* event, ArdourCanvas::Item*,ImageFrameView*) = 0;
|
virtual bool canvas_imageframe_item_view_event(GdkEvent* event, ArdourCanvas::Item*,ImageFrameView*) = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue