Note selection via clicking (including multi-note selection via ctrl/shift clicking).

git-svn-id: svn://localhost/ardour2/trunk@2245 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2007-08-05 00:33:14 +00:00
parent c1b73d4a41
commit c0e916d4da
8 changed files with 120 additions and 37 deletions

View file

@ -83,15 +83,15 @@
<Option name="TrimHandle" value="1900ff44"/> <Option name="TrimHandle" value="1900ff44"/>
<Option name="EditCursor" value="0000ffff"/> <Option name="EditCursor" value="0000ffff"/>
<Option name="PlayHead" value="ff0000ff"/> <Option name="PlayHead" value="ff0000ff"/>
<Option name="MidiSelectRectOutline" value="ff000099"/> <Option name="MidiSelectRectOutline" value="5555ffff"/>
<Option name="MidiSelectRectFill" value="ffdddd33"/> <Option name="MidiSelectRectFill" value="8888ff88"/>
<Option name="MidiNoteOutlineMin" value="44ff4466"/> <Option name="MidiNoteOutlineMin" value="22ff22b0"/>
<Option name="MidiNoteOutlineMid" value="ffff4466"/> <Option name="MidiNoteOutlineMid" value="ffff22b0"/>
<Option name="MidiNoteOutlineMax" value="ff4444ee"/> <Option name="MidiNoteOutlineMax" value="ff2222b0"/>
<Option name="MidiNoteFillMin" value="44ee4433"/> <Option name="MidiNoteFillMin" value="33ee338a"/>
<Option name="MidiNoteFillMid" value="eeee4444"/> <Option name="MidiNoteFillMid" value="eeee338a"/>
<Option name="MidiNoteFillMax" value="dd999955"/> <Option name="MidiNoteFillMax" value="ee33338a"/>
<Option name="MidiNoteSelectedOutline" value="ff000099"/> <Option name="MidiNoteSelectedOutline" value="5566ffee"/>
</Canvas> </Canvas>
</Ardour> </Ardour>

View file

@ -32,11 +32,8 @@ public:
CanvasHit(MidiRegionView& region, Group& group, double size, const ARDOUR::MidiModel::Note* note=NULL) CanvasHit(MidiRegionView& region, Group& group, double size, const ARDOUR::MidiModel::Note* note=NULL)
: Diamond(group, size), CanvasMidiEvent(region, this, note) {} : Diamond(group, size), CanvasMidiEvent(region, this, note) {}
virtual void selected(bool yn) { void set_outline_color(uint32_t c) { property_outline_color_rgba() = c; }
// Temporary hack, no reversal for now void set_fill_color(uint32_t c) { property_fill_color_rgba() = c; }
if (yn)
property_outline_color_rgba() = 0xFF000099;
}
bool on_event(GdkEvent* ev) { return CanvasMidiEvent::on_event(ev); } bool on_event(GdkEvent* ev) { return CanvasMidiEvent::on_event(ev); }
}; };

View file

@ -36,8 +36,26 @@ CanvasMidiEvent::CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOU
, _item(item) , _item(item)
, _state(None) , _state(None)
, _note(note) , _note(note)
, _selected(false)
{ {
} }
void
CanvasMidiEvent::selected(bool yn)
{
if (!_note) {
return;
} else if (yn) {
set_fill_color(UINT_INTERPOLATE(note_fill_color(_note->velocity()),
ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get(), 0.85));
set_outline_color(ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get());
} else {
set_fill_color(note_fill_color(_note->velocity()));
set_outline_color(note_outline_color(_note->velocity()));
}
_selected = yn;
}
bool bool
@ -48,6 +66,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
static double last_x, last_y; static double last_x, last_y;
double event_x, event_y, dx, dy; double event_x, event_y, dx, dy;
nframes_t event_frame; nframes_t event_frame;
bool select_mod = false;
if (_region.get_time_axis_view().editor.current_mouse_mode() != Editing::MouseNote) if (_region.get_time_axis_view().editor.current_mouse_mode() != Editing::MouseNote)
return false; return false;
@ -67,6 +86,11 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
break; break;
case GDK_ENTER_NOTIFY: case GDK_ENTER_NOTIFY:
select_mod = (ev->motion.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
cerr << "ENTER: " << select_mod << " - " << ev->motion.state << endl;
if (select_mod) {
_region.note_selected(this, true);
}
Keyboard::magic_widget_grab_focus(); Keyboard::magic_widget_grab_focus();
_item->grab_focus(); _item->grab_focus();
_region.note_entered(this); _region.note_entered(this);
@ -82,6 +106,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
return true; return true;
case GDK_MOTION_NOTIFY: case GDK_MOTION_NOTIFY:
select_mod = (ev->motion.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
event_x = ev->motion.x; event_x = ev->motion.x;
event_y = ev->motion.y; event_y = ev->motion.y;
//cerr << "MOTION @ " << event_x << ", " << event_y << endl; //cerr << "MOTION @ " << event_x << ", " << event_y << endl;
@ -89,13 +114,15 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
switch (_state) { switch (_state) {
case Pressed: // Drag begin case Pressed: // Drag begin
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, if (!select_mod) {
Gdk::Cursor(Gdk::FLEUR), ev->motion.time); _item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
_state = Dragging; Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
last_x = event_x; _state = Dragging;
last_y = event_y; last_x = event_x;
drag_delta_x = 0; last_y = event_y;
drag_delta_note = 0; drag_delta_x = 0;
drag_delta_note = 0;
}
return true; return true;
case Dragging: // Drag motion case Dragging: // Drag motion
@ -143,6 +170,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
break; break;
case GDK_BUTTON_RELEASE: case GDK_BUTTON_RELEASE:
select_mod = (ev->motion.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
event_x = ev->button.x; event_x = ev->button.x;
event_y = ev->button.y; event_y = ev->button.y;
_item->property_parent().get_value()->w2i(event_x, event_y); _item->property_parent().get_value()->w2i(event_x, event_y);
@ -150,6 +178,14 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
switch (_state) { switch (_state) {
case Pressed: // Clicked case Pressed: // Clicked
_state = None; _state = None;
if (_selected && !select_mod && _region.selection_size() > 1)
_region.unique_select(this);
else if (_selected)
_region.note_deselected(this, select_mod);
else
_region.note_selected(this, select_mod);
return true; return true;
case Dragging: // Dropped case Dragging: // Dropped
_item->ungrab(ev->button.time); _item->ungrab(ev->button.time);

View file

@ -44,9 +44,13 @@ public:
CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOUR::MidiModel::Note* note = NULL); CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOUR::MidiModel::Note* note = NULL);
virtual ~CanvasMidiEvent() {} virtual ~CanvasMidiEvent() {}
virtual bool on_event(GdkEvent* ev); bool on_event(GdkEvent* ev);
virtual void selected(bool yn) = 0; bool selected() const { return _selected; }
void selected(bool yn);
virtual void set_outline_color(uint32_t c) = 0;
virtual void set_fill_color(uint32_t c) = 0;
const ARDOUR::MidiModel::Note* note() { return _note; } const ARDOUR::MidiModel::Note* note() { return _note; }
@ -57,6 +61,7 @@ protected:
Item* const _item; Item* const _item;
State _state; State _state;
const ARDOUR::MidiModel::Note* _note; const ARDOUR::MidiModel::Note* _note;
bool _selected;
}; };
} // namespace Gnome } // namespace Gnome

View file

@ -35,15 +35,8 @@ public:
{ {
} }
virtual void selected(bool yn) { void set_outline_color(uint32_t c) { property_outline_color_rgba() = c; }
if (!_note) void set_fill_color(uint32_t c) { property_fill_color_rgba() = c; }
return;
else if (yn)
property_outline_color_rgba()
= ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get();
else
property_outline_color_rgba() = note_outline_color(_note->velocity());
}
bool on_event(GdkEvent* ev) { return CanvasMidiEvent::on_event(ev); } bool on_event(GdkEvent* ev) { return CanvasMidiEvent::on_event(ev); }
}; };

View file

@ -579,4 +579,47 @@ MidiRegionView::add_note (const MidiModel::Note& note)
} }
} }
void
MidiRegionView::clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev)
{
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i)
if ((*i)->selected() && (*i) != ev)
(*i)->selected(false);
_selection.clear();
}
void
MidiRegionView::unique_select(ArdourCanvas::CanvasMidiEvent* ev)
{
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i)
if ((*i) != ev)
(*i)->selected(false);
_selection.clear();
_selection.insert(ev);
ev->selected(true);
}
void
MidiRegionView::note_selected(ArdourCanvas::CanvasMidiEvent* ev, bool add)
{
if ( ! add)
clear_selection_except(ev);
_selection.insert(ev);
ev->selected(true);
}
void
MidiRegionView::note_deselected(ArdourCanvas::CanvasMidiEvent* ev, bool add)
{
if ( ! add)
clear_selection_except(ev);
_selection.erase(ev);
ev->selected(false);
}

View file

@ -132,6 +132,11 @@ class MidiRegionView : public RegionView
_command_mode = None; _command_mode = None;
} }
void unique_select(ArdourCanvas::CanvasMidiEvent* ev);
void note_selected(ArdourCanvas::CanvasMidiEvent* ev, bool add);
void note_deselected(ArdourCanvas::CanvasMidiEvent* ev, bool add);
size_t selection_size() { return _selection.size(); }
protected: protected:
/* this constructor allows derived types /* this constructor allows derived types
@ -160,6 +165,8 @@ class MidiRegionView : public RegionView
bool canvas_event(GdkEvent* ev); bool canvas_event(GdkEvent* ev);
bool note_canvas_event(GdkEvent* ev); bool note_canvas_event(GdkEvent* ev);
void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev);
double _default_note_length; double _default_note_length;
@ -167,10 +174,12 @@ class MidiRegionView : public RegionView
std::vector<ArdourCanvas::Item*> _events; std::vector<ArdourCanvas::Item*> _events;
ArdourCanvas::CanvasNote** _active_notes; ArdourCanvas::CanvasNote** _active_notes;
ARDOUR::MidiModel::DeltaCommand* _delta_command; ARDOUR::MidiModel::DeltaCommand* _delta_command;
typedef std::set<ArdourCanvas::CanvasMidiEvent*> Selection;
Selection _selection;
enum CommandMode { None, Remove, Delta }; enum CommandMode { None, Remove, Delta };
CommandMode _command_mode; CommandMode _command_mode;
}; };
#endif /* __gtk_ardour_midi_region_view_h__ */ #endif /* __gtk_ardour_midi_region_view_h__ */

View file

@ -43,13 +43,13 @@ inline static uint32_t note_fill_color(uint8_t vel)
{ {
if (vel < 64) { if (vel < 64) {
return UINT_INTERPOLATE( return UINT_INTERPOLATE(
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMin.get(), ARDOUR_UI::config()->canvasvar_MidiNoteFillMin.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMid.get(), ARDOUR_UI::config()->canvasvar_MidiNoteFillMid.get(),
(vel / (double)63.0)); (vel / (double)63.0));
} else { } else {
return UINT_INTERPOLATE( return UINT_INTERPOLATE(
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMid.get(), ARDOUR_UI::config()->canvasvar_MidiNoteFillMid.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMax.get(), ARDOUR_UI::config()->canvasvar_MidiNoteFillMax.get(),
((vel-64) / (double)63.0)); ((vel-64) / (double)63.0));
} }
} }