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="EditCursor" value="0000ffff"/>
<Option name="PlayHead" value="ff0000ff"/>
<Option name="MidiSelectRectOutline" value="ff000099"/>
<Option name="MidiSelectRectFill" value="ffdddd33"/>
<Option name="MidiNoteOutlineMin" value="44ff4466"/>
<Option name="MidiNoteOutlineMid" value="ffff4466"/>
<Option name="MidiNoteOutlineMax" value="ff4444ee"/>
<Option name="MidiNoteFillMin" value="44ee4433"/>
<Option name="MidiNoteFillMid" value="eeee4444"/>
<Option name="MidiNoteFillMax" value="dd999955"/>
<Option name="MidiNoteSelectedOutline" value="ff000099"/>
<Option name="MidiSelectRectOutline" value="5555ffff"/>
<Option name="MidiSelectRectFill" value="8888ff88"/>
<Option name="MidiNoteOutlineMin" value="22ff22b0"/>
<Option name="MidiNoteOutlineMid" value="ffff22b0"/>
<Option name="MidiNoteOutlineMax" value="ff2222b0"/>
<Option name="MidiNoteFillMin" value="33ee338a"/>
<Option name="MidiNoteFillMid" value="eeee338a"/>
<Option name="MidiNoteFillMax" value="ee33338a"/>
<Option name="MidiNoteSelectedOutline" value="5566ffee"/>
</Canvas>
</Ardour>

View File

@ -32,11 +32,8 @@ public:
CanvasHit(MidiRegionView& region, Group& group, double size, const ARDOUR::MidiModel::Note* note=NULL)
: Diamond(group, size), CanvasMidiEvent(region, this, note) {}
virtual void selected(bool yn) {
// Temporary hack, no reversal for now
if (yn)
property_outline_color_rgba() = 0xFF000099;
}
void set_outline_color(uint32_t c) { property_outline_color_rgba() = c; }
void set_fill_color(uint32_t c) { property_fill_color_rgba() = c; }
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)
, _state(None)
, _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
@ -48,6 +66,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
static double last_x, last_y;
double event_x, event_y, dx, dy;
nframes_t event_frame;
bool select_mod = false;
if (_region.get_time_axis_view().editor.current_mouse_mode() != Editing::MouseNote)
return false;
@ -67,6 +86,11 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
break;
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();
_item->grab_focus();
_region.note_entered(this);
@ -82,6 +106,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
return true;
case GDK_MOTION_NOTIFY:
select_mod = (ev->motion.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
event_x = ev->motion.x;
event_y = ev->motion.y;
//cerr << "MOTION @ " << event_x << ", " << event_y << endl;
@ -89,13 +114,15 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
switch (_state) {
case Pressed: // Drag begin
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
_state = Dragging;
last_x = event_x;
last_y = event_y;
drag_delta_x = 0;
drag_delta_note = 0;
if (!select_mod) {
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
_state = Dragging;
last_x = event_x;
last_y = event_y;
drag_delta_x = 0;
drag_delta_note = 0;
}
return true;
case Dragging: // Drag motion
@ -143,6 +170,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
break;
case GDK_BUTTON_RELEASE:
select_mod = (ev->motion.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
event_x = ev->button.x;
event_y = ev->button.y;
_item->property_parent().get_value()->w2i(event_x, event_y);
@ -150,6 +178,14 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
switch (_state) {
case Pressed: // Clicked
_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;
case Dragging: // Dropped
_item->ungrab(ev->button.time);

View File

@ -44,9 +44,13 @@ public:
CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOUR::MidiModel::Note* note = NULL);
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; }
@ -57,6 +61,7 @@ protected:
Item* const _item;
State _state;
const ARDOUR::MidiModel::Note* _note;
bool _selected;
};
} // namespace Gnome

View File

@ -35,15 +35,8 @@ public:
{
}
virtual void selected(bool yn) {
if (!_note)
return;
else if (yn)
property_outline_color_rgba()
= ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get();
else
property_outline_color_rgba() = note_outline_color(_note->velocity());
}
void set_outline_color(uint32_t c) { property_outline_color_rgba() = c; }
void set_fill_color(uint32_t c) { property_fill_color_rgba() = c; }
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;
}
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:
/* this constructor allows derived types
@ -160,6 +165,8 @@ class MidiRegionView : public RegionView
bool canvas_event(GdkEvent* ev);
bool note_canvas_event(GdkEvent* ev);
void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev);
double _default_note_length;
@ -167,10 +174,12 @@ class MidiRegionView : public RegionView
std::vector<ArdourCanvas::Item*> _events;
ArdourCanvas::CanvasNote** _active_notes;
ARDOUR::MidiModel::DeltaCommand* _delta_command;
typedef std::set<ArdourCanvas::CanvasMidiEvent*> Selection;
Selection _selection;
enum CommandMode { None, Remove, Delta };
CommandMode _command_mode;
};
#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) {
return UINT_INTERPOLATE(
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMin.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMid.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteFillMin.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteFillMid.get(),
(vel / (double)63.0));
} else {
return UINT_INTERPOLATE(
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMid.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteOutlineMax.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteFillMid.get(),
ARDOUR_UI::config()->canvasvar_MidiNoteFillMax.get(),
((vel-64) / (double)63.0));
}
}