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
Signed by: rgareus
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)
, _master_widget (16, 16)
, _master (_master_widget.root ())
, _selection (*this, *this)
{
load_bindings ();
register_actions ();
@ -266,6 +267,7 @@ TriggerPage::set_session (Session* s)
_trigger_route_list.set_session (s);
if (!_session) {
_selection.clear ();
return;
}
@ -297,6 +299,10 @@ TriggerPage::set_session (Session* s)
update_title ();
start_updating ();
selection_changed ();
PBD::PropertyChange sc;
sc.add (Properties::selected);
_selection.presentation_info_changed (sc);
}
void
@ -312,6 +318,7 @@ TriggerPage::session_going_away ()
delete (*i);
}
#endif
_selection.clear ();
_strips.clear ();
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)->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 ();
}
@ -464,6 +472,7 @@ void
TriggerPage::redisplay_track_list ()
{
_strips.sort (TriggerStripSorter ());
PresentationInfo::ChangeSuspender cs;
for (list<TriggerStrip*>::iterator i = _strips.begin (); i != _strips.end (); ++i) {
TriggerStrip* strip = *i;
@ -472,6 +481,12 @@ TriggerPage::redisplay_track_list ()
bool hidden = s->presentation_info ().hidden ();
if (s->is_selected ()) {
_selection.add (*i);
} else {
_selection.remove (*i);
}
if (!(s)->presentation_info ().trigger_track ()) {
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
TriggerPage::rec_state_clicked ()
{
@ -512,6 +546,9 @@ TriggerPage::parameter_changed (string const& p)
void
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)) {
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
TriggerPage::no_strip_button_event (GdkEventButton* ev)
{

View File

@ -38,6 +38,7 @@
#include "midi_region_operations_box.h"
#include "midi_region_properties_box.h"
#include "midi_trigger_properties_box.h"
#include "route_processor_selection.h"
#include "slot_properties_box.h"
#include "trigger_clip_picker.h"
#include "trigger_region_list.h"
@ -47,7 +48,7 @@
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:
TriggerPage ();
@ -60,6 +61,8 @@ public:
Gtk::Window* use_own_window (bool and_fill_it);
RouteProcessorSelection& selection() { return _selection; }
private:
void load_bindings ();
void register_actions ();
@ -80,6 +83,7 @@ private:
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_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);
@ -87,6 +91,9 @@ private:
bool idle_drop_paths (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 ();
PBD::ScopedConnectionList editor_connections;
@ -130,6 +137,7 @@ private:
MidiClipEditorBox _midi_trim_box;
#endif
RouteProcessorSelection _selection;
std::list<TriggerStrip*> _strips;
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
TriggerStrip::route_color_changed ()
{

View File

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

View File

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