mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-10 07:26:32 +01:00
tweak EditingContext APIs to get context menus in pianoroll working sensibly
There is now a separate context menu for note-context clicks and "region" context clicks. Something similar may be desirable for timeline editing too
This commit is contained in:
parent
5223cbdc18
commit
08da5255fe
4 changed files with 118 additions and 39 deletions
|
|
@ -1783,8 +1783,12 @@ EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* eve
|
|||
entered_regionview. */
|
||||
|
||||
MidiView& mrv = note->midi_view();
|
||||
const RegionSelection rs = region_selection ();
|
||||
const uint32_t sel_size = mrv.selection_size ();
|
||||
MidiViews mvs (midiviews_from_region_selection (region_selection ()));
|
||||
|
||||
if (std::find (mvs.begin(), mvs.end(), &mrv) == mvs.end()) {
|
||||
mvs.push_back (&mrv);
|
||||
}
|
||||
|
||||
MenuList& items = _note_context_menu.items();
|
||||
items.clear();
|
||||
|
|
@ -1794,17 +1798,17 @@ EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* eve
|
|||
}
|
||||
|
||||
items.push_back(MenuElem(_("Edit..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::edit_notes), &mrv)));
|
||||
items.push_back(MenuElem(_("Transpose..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transpose_regions), rs)));
|
||||
items.push_back(MenuElem(_("Legatize"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), rs, false)));
|
||||
items.push_back(MenuElem(_("Transpose..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transpose_regions), mvs)));
|
||||
items.push_back(MenuElem(_("Legatize"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, false)));
|
||||
if (sel_size < 2) {
|
||||
items.back().set_sensitive (false);
|
||||
}
|
||||
items.push_back(MenuElem(_("Quantize..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::quantize_regions), rs)));
|
||||
items.push_back(MenuElem(_("Remove Overlap"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), rs, true)));
|
||||
items.push_back(MenuElem(_("Quantize..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::quantize_regions), mvs)));
|
||||
items.push_back(MenuElem(_("Remove Overlap"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, true)));
|
||||
if (sel_size < 2) {
|
||||
items.back().set_sensitive (false);
|
||||
}
|
||||
items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), rs)));
|
||||
items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), mvs)));
|
||||
|
||||
_note_context_menu.popup (event->button.button, event->button.time);
|
||||
}
|
||||
|
|
@ -1822,13 +1826,19 @@ EditingContext::button_settings () const
|
|||
return node;
|
||||
}
|
||||
|
||||
std::vector<MidiView*>
|
||||
EditingContext::MidiViews
|
||||
EditingContext::filter_to_unique_midi_region_views (RegionSelection const & rs) const
|
||||
{
|
||||
return filter_to_unique_midi_region_views (midiviews_from_region_selection (rs));
|
||||
}
|
||||
|
||||
EditingContext::MidiViews
|
||||
EditingContext::filter_to_unique_midi_region_views (MidiViews const & mvs) const
|
||||
{
|
||||
typedef std::pair<std::shared_ptr<MidiSource>,timepos_t> MapEntry;
|
||||
std::set<MapEntry> single_region_set;
|
||||
|
||||
std::vector<MidiView*> views;
|
||||
MidiViews views;
|
||||
|
||||
/* build a list of regions that are unique with respect to their source
|
||||
* and start position. Note: this is non-exhaustive... if someone has a
|
||||
|
|
@ -1839,17 +1849,26 @@ EditingContext::filter_to_unique_midi_region_views (RegionSelection const & rs)
|
|||
* Solution: user should not select both regions, or should fork one of them.
|
||||
*/
|
||||
|
||||
for (auto const & rv : rs) {
|
||||
for (auto const & mv : mvs) {
|
||||
|
||||
MidiView* mrv = dynamic_cast<MidiView*> (rv);
|
||||
|
||||
if (!mrv) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MapEntry entry = make_pair (mrv->midi_region()->midi_source(), mrv->midi_region()->start());
|
||||
MapEntry entry = make_pair (mv->midi_region()->midi_source(), mv->midi_region()->start());
|
||||
|
||||
if (single_region_set.insert (entry).second) {
|
||||
views.push_back (mv);
|
||||
}
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
EditingContext::MidiViews
|
||||
EditingContext::midiviews_from_region_selection (RegionSelection const & rs) const
|
||||
{
|
||||
MidiViews views;
|
||||
|
||||
for (auto & rv : rs) {
|
||||
MidiView* mrv = dynamic_cast<MidiView*> (rv);
|
||||
if (mrv) {
|
||||
views.push_back (mrv);
|
||||
}
|
||||
}
|
||||
|
|
@ -1861,14 +1880,15 @@ void
|
|||
EditingContext::quantize_region ()
|
||||
{
|
||||
if (_session) {
|
||||
quantize_regions(region_selection ());
|
||||
quantize_regions (midiviews_from_region_selection (region_selection()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::quantize_regions (const RegionSelection& rs)
|
||||
EditingContext::quantize_regions (const MidiViews& rs)
|
||||
{
|
||||
if (rs.n_midi_regions() == 0) {
|
||||
if (rs.empty()) {
|
||||
std::cerr << "no regions\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1889,18 +1909,18 @@ void
|
|||
EditingContext::legatize_region (bool shrink_only)
|
||||
{
|
||||
if (_session) {
|
||||
legatize_regions(region_selection (), shrink_only);
|
||||
legatize_regions (midiviews_from_region_selection (region_selection ()), shrink_only);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::legatize_regions (const RegionSelection& rs, bool shrink_only)
|
||||
EditingContext::legatize_regions (const MidiViews& rs, bool shrink_only)
|
||||
{
|
||||
if (rs.n_midi_regions() == 0) {
|
||||
if (rs.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Legatize legatize(shrink_only);
|
||||
Legatize legatize (shrink_only);
|
||||
apply_midi_note_edit_op (legatize, rs);
|
||||
}
|
||||
|
||||
|
|
@ -1908,14 +1928,14 @@ void
|
|||
EditingContext::transform_region ()
|
||||
{
|
||||
if (_session) {
|
||||
transform_regions(region_selection ());
|
||||
transform_regions (midiviews_from_region_selection (region_selection ()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::transform_regions (const RegionSelection& rs)
|
||||
EditingContext::transform_regions (const MidiViews& rs)
|
||||
{
|
||||
if (rs.n_midi_regions() == 0) {
|
||||
if (rs.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1935,14 +1955,14 @@ void
|
|||
EditingContext::transpose_region ()
|
||||
{
|
||||
if (_session) {
|
||||
transpose_regions(region_selection ());
|
||||
transpose_regions (midiviews_from_region_selection (region_selection ()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::transpose_regions (const RegionSelection& rs)
|
||||
EditingContext::transpose_regions (const MidiViews& rs)
|
||||
{
|
||||
if (rs.n_midi_regions() == 0) {
|
||||
if (rs.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1987,8 +2007,6 @@ EditingContext::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiView& m
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::cerr << "Apply op to " << selected.size() << std::endl;
|
||||
|
||||
std::vector<Evoral::Sequence<Temporal::Beats>::Notes> v;
|
||||
v.push_back (selected);
|
||||
|
||||
|
|
@ -1999,6 +2017,12 @@ EditingContext::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiView& m
|
|||
|
||||
void
|
||||
EditingContext::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs)
|
||||
{
|
||||
apply_midi_note_edit_op (op, midiviews_from_region_selection (rs));
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::apply_midi_note_edit_op (MidiOperator& op, const MidiViews& rs)
|
||||
{
|
||||
if (rs.empty()) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -395,18 +395,29 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
|
|||
PBD::Signal<void()> SnapChanged;
|
||||
PBD::Signal<void()> MouseModeChanged;
|
||||
|
||||
typedef std::vector<MidiView*> MidiViews;
|
||||
|
||||
/* MIDI actions, proxied to selected MidiRegionView(s) */
|
||||
ARDOUR::Quantize* get_quantize_op ();
|
||||
void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const RegionSelection& rs);
|
||||
void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const MidiViews& rs);
|
||||
PBD::Command* apply_midi_note_edit_op_to_region (ARDOUR::MidiOperator& op, MidiView& mrv);
|
||||
virtual void midi_action (void (MidiView::*method)());
|
||||
std::vector<MidiView*> filter_to_unique_midi_region_views (RegionSelection const & ms) const;
|
||||
std::vector<MidiView*> filter_to_unique_midi_region_views (RegionSelection const & rs) const;
|
||||
std::vector<MidiView*> filter_to_unique_midi_region_views (MidiViews const & ms) const;
|
||||
|
||||
void quantize_region ();
|
||||
void transform_region ();
|
||||
void legatize_region (bool shrink_only);
|
||||
void transpose_region ();
|
||||
|
||||
void quantize_regions (const MidiViews& rs);
|
||||
void legatize_regions (const MidiViews& rs, bool shrink_only);
|
||||
void transform_regions (const MidiViews& rs);
|
||||
void transpose_regions (const MidiViews& rs);
|
||||
|
||||
void edit_notes (MidiView*);
|
||||
|
||||
static bool need_shared_actions;
|
||||
void register_midi_actions (Gtkmm2ext::Bindings*, std::string const &);
|
||||
void register_common_actions (Gtkmm2ext::Bindings*, std::string const &);
|
||||
|
|
@ -666,13 +677,9 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
|
|||
|
||||
virtual RegionSelection region_selection() = 0;
|
||||
|
||||
void edit_notes (MidiView*);
|
||||
void note_edit_done (int, EditNoteDialog*);
|
||||
|
||||
void quantize_regions (const RegionSelection& rs);
|
||||
void legatize_regions (const RegionSelection& rs, bool shrink_only);
|
||||
void transform_regions (const RegionSelection& rs);
|
||||
void transpose_regions (const RegionSelection& rs);
|
||||
MidiViews midiviews_from_region_selection (RegionSelection const &) const;
|
||||
|
||||
/** the adjustment that controls the overall editing vertical scroll position */
|
||||
friend class EditorSummary;
|
||||
|
|
|
|||
|
|
@ -1133,9 +1133,9 @@ Pianoroll::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, It
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Keyboard::is_context_menu_event (&event->button)) {
|
||||
} else {
|
||||
|
||||
switch (item_type) {
|
||||
case NoteItem:
|
||||
if (internal_editing()) {
|
||||
|
|
@ -1143,14 +1143,58 @@ Pianoroll::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, It
|
|||
return true;
|
||||
}
|
||||
break;
|
||||
case RegionItem:
|
||||
if (internal_editing()) {
|
||||
popup_region_context_menu (item, event);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
popup_note_context_menu (item, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Pianoroll::popup_region_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
using namespace Gtk::Menu_Helpers;
|
||||
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t sel_size = view->selection_size ();
|
||||
MidiViews mvs ({view});
|
||||
|
||||
MenuList& items = _region_context_menu.items();
|
||||
items.clear();
|
||||
|
||||
if (sel_size > 0) {
|
||||
items.push_back (MenuElem(_("Delete"), sigc::mem_fun (*view, &MidiView::delete_selection)));
|
||||
}
|
||||
|
||||
items.push_back(MenuElem(_("Edit..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::edit_notes), view)));
|
||||
items.push_back(MenuElem(_("Transpose..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transpose_regions), mvs)));
|
||||
items.push_back(MenuElem(_("Legatize"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, false)));
|
||||
if (sel_size < 2) {
|
||||
items.back().set_sensitive (false);
|
||||
}
|
||||
items.push_back(MenuElem(_("Quantize..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::quantize_regions), mvs)));
|
||||
items.push_back(MenuElem(_("Remove Overlap"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, true)));
|
||||
if (sel_size < 2) {
|
||||
items.back().set_sensitive (false);
|
||||
}
|
||||
items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), mvs)));
|
||||
|
||||
_region_context_menu.popup (event->button.button, event->button.time);
|
||||
}
|
||||
|
||||
bool
|
||||
Pianoroll::button_press_dispatch (GdkEventButton* ev)
|
||||
{
|
||||
|
|
@ -1233,6 +1277,7 @@ RegionSelection
|
|||
Pianoroll::region_selection()
|
||||
{
|
||||
RegionSelection rs;
|
||||
/* there is never any region-level selection in a pianoroll */
|
||||
return rs;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -349,4 +349,7 @@ class Pianoroll : public CueEditor
|
|||
void ruler_locate (GdkEventButton*);
|
||||
void scrolled ();
|
||||
void update_tempo_based_rulers ();
|
||||
|
||||
Gtk::Menu _region_context_menu;
|
||||
void popup_region_context_menu (ArdourCanvas::Item* item, GdkEvent* event);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue