Implement TriggerStrip selection

This also changes TriggerBox Selection to act on release
(like all other selection). Otherwise strip selection will
de-select the TriggerBox on mouse-release.
This commit is contained in:
Robin Gareus 2022-02-03 05:39:48 +01:00
parent fd3d17562c
commit 511ff3290f
No known key found for this signature in database
GPG key ID: A090BCE02CF57F04
5 changed files with 148 additions and 2 deletions

View file

@ -69,6 +69,7 @@ TriggerPage::TriggerPage ()
, _cue_box (16, 16 * default_triggers_per_box) , _cue_box (16, 16 * default_triggers_per_box)
, _master_widget (16, 16) , _master_widget (16, 16)
, _master (_master_widget.root ()) , _master (_master_widget.root ())
, _selection (*this, *this)
{ {
load_bindings (); load_bindings ();
register_actions (); register_actions ();
@ -266,6 +267,7 @@ TriggerPage::set_session (Session* s)
_trigger_route_list.set_session (s); _trigger_route_list.set_session (s);
if (!_session) { if (!_session) {
_selection.clear ();
return; return;
} }
@ -297,6 +299,10 @@ TriggerPage::set_session (Session* s)
update_title (); update_title ();
start_updating (); start_updating ();
selection_changed (); selection_changed ();
PBD::PropertyChange sc;
sc.add (Properties::selected);
_selection.presentation_info_changed (sc);
} }
void void
@ -312,6 +318,7 @@ TriggerPage::session_going_away ()
delete (*i); delete (*i);
} }
#endif #endif
_selection.clear ();
_strips.clear (); _strips.clear ();
SessionHandlePtr::session_going_away (); SessionHandlePtr::session_going_away ();
@ -432,6 +439,7 @@ TriggerPage::add_routes (RouteList& rl)
(*r)->presentation_info ().PropertyChanged.connect (*this, invalidator (*this), boost::bind (&TriggerPage::stripable_property_changed, this, _1, boost::weak_ptr<Stripable> (*r)), gui_context ()); (*r)->presentation_info ().PropertyChanged.connect (*this, invalidator (*this), boost::bind (&TriggerPage::stripable_property_changed, this, _1, boost::weak_ptr<Stripable> (*r)), gui_context ());
(*r)->PropertyChanged.connect (*this, invalidator (*this), boost::bind (&TriggerPage::stripable_property_changed, this, _1, boost::weak_ptr<Stripable> (*r)), gui_context ()); (*r)->PropertyChanged.connect (*this, invalidator (*this), boost::bind (&TriggerPage::stripable_property_changed, this, _1, boost::weak_ptr<Stripable> (*r)), gui_context ());
ts->signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &TriggerPage::strip_button_release_event), ts));
} }
redisplay_track_list (); redisplay_track_list ();
} }
@ -464,6 +472,7 @@ void
TriggerPage::redisplay_track_list () TriggerPage::redisplay_track_list ()
{ {
_strips.sort (TriggerStripSorter ()); _strips.sort (TriggerStripSorter ());
PresentationInfo::ChangeSuspender cs;
for (list<TriggerStrip*>::iterator i = _strips.begin (); i != _strips.end (); ++i) { for (list<TriggerStrip*>::iterator i = _strips.begin (); i != _strips.end (); ++i) {
TriggerStrip* strip = *i; TriggerStrip* strip = *i;
@ -472,6 +481,12 @@ TriggerPage::redisplay_track_list ()
bool hidden = s->presentation_info ().hidden (); bool hidden = s->presentation_info ().hidden ();
if (s->is_selected ()) {
_selection.add (*i);
} else {
_selection.remove (*i);
}
if (!(s)->presentation_info ().trigger_track ()) { if (!(s)->presentation_info ().trigger_track ()) {
hidden = true; hidden = true;
} }
@ -492,6 +507,25 @@ TriggerPage::redisplay_track_list ()
} }
} }
AxisView*
TriggerPage::axis_view_by_stripable (boost::shared_ptr<Stripable> s) const
{
for (list<TriggerStrip*>::const_iterator i = _strips.begin (); i != _strips.end (); ++i) {
TriggerStrip* strip = *i;
if (s == strip->stripable ()) {
return strip;
}
}
return 0;
}
AxisView*
TriggerPage::axis_view_by_control (boost::shared_ptr<AutomationControl> c) const
{
return 0;
}
void void
TriggerPage::rec_state_clicked () TriggerPage::rec_state_clicked ()
{ {
@ -512,6 +546,9 @@ TriggerPage::parameter_changed (string const& p)
void void
TriggerPage::pi_property_changed (PBD::PropertyChange const& what_changed) TriggerPage::pi_property_changed (PBD::PropertyChange const& what_changed)
{ {
if (what_changed.contains (Properties::selected)) {
_selection.presentation_info_changed (what_changed);
}
if (what_changed.contains (ARDOUR::Properties::order)) { if (what_changed.contains (ARDOUR::Properties::order)) {
redisplay_track_list (); redisplay_track_list ();
} }
@ -535,6 +572,87 @@ TriggerPage::stripable_property_changed (PBD::PropertyChange const& what_changed
} }
} }
bool
TriggerPage::strip_button_release_event (GdkEventButton *ev, TriggerStrip *strip)
{
if (ev->button != 1) {
return false;
}
if (_selection.selected (strip)) {
/* primary-click: toggle selection state of strip */
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
_selection.remove (strip, true);
} else if (_selection.axes.size() > 1) {
/* de-select others */
_selection.set (strip);
}
PublicEditor& pe = PublicEditor::instance();
TimeAxisView* tav = pe.time_axis_view_from_stripable (strip->stripable());
if (tav) {
pe.set_selected_mixer_strip (*tav);
}
} else {
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
_selection.add (strip, true);
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::RangeSelectModifier)) {
/* extend selection */
vector<TriggerStrip*> tmp;
bool accumulate = false;
bool found_another = false;
_strips.sort (TriggerStripSorter ());
for (list<TriggerStrip*>::iterator i = _strips.begin (); i != _strips.end (); ++i) {
TriggerStrip* ts = *i;
if (ts == strip) {
/* hit clicked strip, start accumulating till we hit the first
selected strip
*/
if (accumulate) {
/* done */
break;
} else {
accumulate = true;
}
} else if (_selection.selected (ts)) {
/* hit selected strip. if currently accumulating others,
we're done. if not accumulating others, start doing so.
*/
found_another = true;
if (accumulate) {
/* done */
break;
} else {
accumulate = true;
}
} else {
if (accumulate) {
tmp.push_back (ts);
}
}
}
tmp.push_back (strip);
if (found_another) {
PresentationInfo::ChangeSuspender cs;
for (vector<TriggerStrip*>::iterator i = tmp.begin(); i != tmp.end(); ++i) {
_selection.add (*i, true);
}
} else {
_selection.set (strip); //user wants to start a range selection, but there aren't any others selected yet
}
} else {
_selection.set (strip);
}
}
return true;
}
bool bool
TriggerPage::no_strip_button_event (GdkEventButton* ev) TriggerPage::no_strip_button_event (GdkEventButton* ev)
{ {

View file

@ -38,6 +38,7 @@
#include "midi_region_operations_box.h" #include "midi_region_operations_box.h"
#include "midi_region_properties_box.h" #include "midi_region_properties_box.h"
#include "midi_trigger_properties_box.h" #include "midi_trigger_properties_box.h"
#include "route_processor_selection.h"
#include "slot_properties_box.h" #include "slot_properties_box.h"
#include "trigger_clip_picker.h" #include "trigger_clip_picker.h"
#include "trigger_region_list.h" #include "trigger_region_list.h"
@ -47,7 +48,7 @@
class TriggerStrip; class TriggerStrip;
class TriggerPage : public ArdourWidgets::Tabbable, public ARDOUR::SessionHandlePtr, public PBD::ScopedConnectionList class TriggerPage : public ArdourWidgets::Tabbable, public ARDOUR::SessionHandlePtr, public PBD::ScopedConnectionList, public AxisViewProvider
{ {
public: public:
TriggerPage (); TriggerPage ();
@ -60,6 +61,8 @@ public:
Gtk::Window* use_own_window (bool and_fill_it); Gtk::Window* use_own_window (bool and_fill_it);
RouteProcessorSelection& selection() { return _selection; }
private: private:
void load_bindings (); void load_bindings ();
void register_actions (); void register_actions ();
@ -80,6 +83,7 @@ private:
void add_sidebar_page (std::string const&, Gtk::Widget&); void add_sidebar_page (std::string const&, Gtk::Widget&);
bool strip_button_release_event (GdkEventButton*, TriggerStrip*);
bool no_strip_button_event (GdkEventButton*); bool no_strip_button_event (GdkEventButton*);
bool no_strip_drag_motion (Glib::RefPtr<Gdk::DragContext> const&, int, int, guint); bool no_strip_drag_motion (Glib::RefPtr<Gdk::DragContext> const&, int, int, guint);
void no_strip_drag_data_received (Glib::RefPtr<Gdk::DragContext> const&, int, int, Gtk::SelectionData const&, guint, guint); void no_strip_drag_data_received (Glib::RefPtr<Gdk::DragContext> const&, int, int, Gtk::SelectionData const&, guint, guint);
@ -87,6 +91,9 @@ private:
bool idle_drop_paths (std::vector<std::string>); bool idle_drop_paths (std::vector<std::string>);
void drop_paths_part_two (std::vector<std::string>); void drop_paths_part_two (std::vector<std::string>);
AxisView* axis_view_by_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
AxisView* axis_view_by_control (boost::shared_ptr<ARDOUR::AutomationControl>) const;
void selection_changed (); void selection_changed ();
PBD::ScopedConnectionList editor_connections; PBD::ScopedConnectionList editor_connections;
@ -130,6 +137,7 @@ private:
MidiClipEditorBox _midi_trim_box; MidiClipEditorBox _midi_trim_box;
#endif #endif
RouteProcessorSelection _selection;
std::list<TriggerStrip*> _strips; std::list<TriggerStrip*> _strips;
sigc::connection _fast_screen_update_connection; sigc::connection _fast_screen_update_connection;
}; };

View file

@ -403,6 +403,22 @@ TriggerStrip::route_property_changed (const PropertyChange& what_changed)
} }
} }
void
TriggerStrip::set_selected (bool yn)
{
AxisView::set_selected (yn);
if (selected()) {
global_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
global_frame.set_name ("MixerStripSelectedFrame");
} else {
global_frame.set_shadow_type (Gtk::SHADOW_IN);
global_frame.set_name ("MixerStripFrame");
}
global_frame.queue_draw ();
}
void void
TriggerStrip::route_color_changed () TriggerStrip::route_color_changed ()
{ {

View file

@ -59,6 +59,7 @@ public:
} }
void set_session (ARDOUR::Session* s); void set_session (ARDOUR::Session* s);
void set_selected (bool yn);
void fast_update (); void fast_update ();

View file

@ -563,7 +563,6 @@ TriggerEntry::name_button_event (GdkEvent* ev)
} }
break; break;
case GDK_BUTTON_PRESS: case GDK_BUTTON_PRESS:
PublicEditor::instance ().get_selection ().set (this);
break; break;
case GDK_2BUTTON_PRESS: case GDK_2BUTTON_PRESS:
#if SELECTION_PROPERTIES_BOX_TODO #if SELECTION_PROPERTIES_BOX_TODO
@ -573,8 +572,12 @@ TriggerEntry::name_button_event (GdkEvent* ev)
case GDK_BUTTON_RELEASE: case GDK_BUTTON_RELEASE:
switch (ev->button.button) { switch (ev->button.button) {
case 3: case 3:
PublicEditor::instance ().get_selection ().set (this);
context_menu (); context_menu ();
return true; return true;
case 1:
PublicEditor::instance ().get_selection ().set (this);
return true;
default: default:
break; break;
} }