From 1f772d30d365dbf671c87a57280ba6e799731369 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 26 Aug 2023 03:18:45 +0200 Subject: [PATCH] Update Location UI to include section marker flags --- gtk2_ardour/editor_sections.cc | 107 +++++++++++++++++++++++++++++---- gtk2_ardour/editor_sections.h | 13 +++- gtk2_ardour/location_ui.cc | 40 ++++++++++-- gtk2_ardour/location_ui.h | 2 + 4 files changed, 142 insertions(+), 20 deletions(-) diff --git a/gtk2_ardour/editor_sections.cc b/gtk2_ardour/editor_sections.cc index d55fed0513..339d097737 100644 --- a/gtk2_ardour/editor_sections.cc +++ b/gtk2_ardour/editor_sections.cc @@ -21,9 +21,13 @@ #include "ardour/session.h" #include "pbd/unwind.h" +#include "gtkmm2ext/keyboard.h" + #include "ardour_ui.h" #include "editor_sections.h" #include "gui_thread.h" +#include "keyboard.h" +#include "main_clock.h" #include "public_editor.h" #include "utils.h" @@ -35,11 +39,14 @@ using namespace Gtk; using namespace ARDOUR; EditorSections::EditorSections () - : _ignore_redisplay (false) + : _old_focus (0) + , _no_redisplay (false) { _model = ListStore::create (_columns); _view.set_model (_model); _view.append_column (_("Name"), _columns.name); + _view.append_column (_("Start"), _columns.s_start); + _view.append_column (_("End"), _columns.s_end); _view.set_headers_visible (true); _view.get_selection ()->set_mode (Gtk::SELECTION_SINGLE); @@ -61,6 +68,14 @@ EditorSections::EditorSections () _view.signal_drag_motion ().connect (sigc::mem_fun (*this, &EditorSections::drag_motion)); _view.signal_drag_leave ().connect (sigc::mem_fun (*this, &EditorSections::drag_leave)); _view.signal_drag_data_received ().connect (sigc::mem_fun (*this, &EditorSections::drag_data_received)); + + /* Allow to scroll using key up/down */ + _view.signal_enter_notify_event ().connect (sigc::mem_fun (*this, &EditorSections::enter_notify), false); + _view.signal_leave_notify_event ().connect (sigc::mem_fun (*this, &EditorSections::leave_notify), false); + _scroller.signal_focus_in_event ().connect (sigc::mem_fun (*this, &EditorSections::focus_in), false); + _scroller.signal_focus_out_event ().connect (sigc::mem_fun (*this, &EditorSections::focus_out)); + + ARDOUR_UI::instance ()->primary_clock->mode_changed.connect (sigc::mem_fun (*this, &EditorSections::clock_format_changed)); } void @@ -85,7 +100,7 @@ EditorSections::set_session (Session* s) void EditorSections::redisplay () { - if (_ignore_redisplay) { + if (_no_redisplay) { return; } _view.set_model (Glib::RefPtr ()); @@ -112,32 +127,51 @@ EditorSections::redisplay () } } while (l); + clock_format_changed (); + _view.set_model (_model); } +void +EditorSections::clock_format_changed () +{ + if (!_session) { + return; + } + + TreeModel::Children rows = _model->children (); + for (auto const& r : rows) { + char buf[16]; + ARDOUR_UI_UTILS::format_position (_session, r[_columns.start], buf, sizeof (buf)); + r[_columns.s_start] = buf; + ARDOUR_UI_UTILS::format_position (_session, r[_columns.end], buf, sizeof (buf)); + r[_columns.s_end] = buf; + } +} + bool EditorSections::scroll_row_timeout () { - int y; - Gdk::Rectangle visible_rect; + int y; + Gdk::Rectangle visible_rect; Gtk::Adjustment* adj = _scroller.get_vadjustment (); - gdk_window_get_pointer (_view.get_window ()->gobj(), NULL, &y, NULL); + gdk_window_get_pointer (_view.get_window ()->gobj (), NULL, &y, NULL); _view.get_visible_rect (visible_rect); y += adj->get_value (); int offset = y - (visible_rect.get_y () + 30); if (offset > 0) { - offset = y - (visible_rect.get_y() + visible_rect.get_height() - 30); + offset = y - (visible_rect.get_y () + visible_rect.get_height () - 30); if (offset < 0) { return true; } } float value = adj->get_value () + offset; - value = std::max (0, value); - value = std::min (value, adj->get_upper () - adj->get_page_size ()); + value = std::max (0, value); + value = std::min (value, adj->get_upper () - adj->get_page_size ()); adj->set_value (value); return true; @@ -150,7 +184,7 @@ EditorSections::selection_changed () if (rows.empty ()) { return; } - Gtk::TreeModel::Row row = *_model->get_iter (*rows.begin ()); + Gtk::TreeModel::Row row = *_model->get_iter (*rows.begin ()); timepos_t start = row[_columns.start]; timepos_t end = row[_columns.end]; @@ -225,7 +259,7 @@ EditorSections::drag_motion (Glib::RefPtr const& context, int _view.drag_highlight (); if (!_scroll_timeout.connected ()) { - _scroll_timeout = Glib::signal_timeout().connect (sigc::mem_fun (*this, &EditorSections::scroll_row_timeout), 150); + _scroll_timeout = Glib::signal_timeout ().connect (sigc::mem_fun (*this, &EditorSections::scroll_row_timeout), 150); } return true; @@ -296,10 +330,10 @@ EditorSections::drag_data_received (Glib::RefPtr const& contex } #ifndef NDEBUG - cout << "cut copy '" << s.location->name () << "' " << s.start << " - " << s.end << " to " << to << "\n"; + cout << "cut copy '" << s.location->name () << "' " << s.start << " - " << s.end << " to " << to << " op = " << op << "\n"; #endif { - PBD::Unwinder uw (_ignore_redisplay, true); + PBD::Unwinder uw (_no_redisplay, true); _session->cut_copy_section (s.start, s.end, to, op); } redisplay (); @@ -329,9 +363,56 @@ EditorSections::key_release (GdkEventKey* ev) timepos_t start = row[_columns.start]; timepos_t end = row[_columns.end]; { - PBD::Unwinder uw (_ignore_redisplay, true); + PBD::Unwinder uw (_no_redisplay, true); _session->cut_copy_section (start, end, timepos_t (0), DeleteSection); } redisplay (); return true; } + +bool +EditorSections::focus_in (GdkEventFocus*) +{ + Window* win = dynamic_cast (_scroller.get_toplevel ()); + + if (win) { + _old_focus = win->get_focus (); + } else { + _old_focus = 0; + } + + /* try to do nothing on focus in (doesn't work, hence selection_count nonsense) */ + return true; +} + +bool +EditorSections::focus_out (GdkEventFocus*) +{ + if (_old_focus) { + _old_focus->grab_focus (); + _old_focus = 0; + } + return false; +} + +bool +EditorSections::enter_notify (GdkEventCrossing*) +{ + Gtkmm2ext::Keyboard::magic_widget_grab_focus (); + return false; +} + +bool +EditorSections::leave_notify (GdkEventCrossing* ev) +{ + if (_old_focus) { + _old_focus->grab_focus (); + _old_focus = 0; + } + + if (ev->detail != GDK_NOTIFY_INFERIOR && ev->detail != GDK_NOTIFY_ANCESTOR) { + Gtkmm2ext::Keyboard::magic_widget_drop_focus (); + } + + return false; +} diff --git a/gtk2_ardour/editor_sections.h b/gtk2_ardour/editor_sections.h index 4260928571..6f8bed60a6 100644 --- a/gtk2_ardour/editor_sections.h +++ b/gtk2_ardour/editor_sections.h @@ -50,6 +50,12 @@ private: bool key_release (GdkEventKey*); void selection_changed (); bool scroll_row_timeout (); + void clock_format_changed (); + + bool focus_in (GdkEventFocus*); + bool focus_out (GdkEventFocus*); + bool enter_notify (GdkEventCrossing*); + bool leave_notify (GdkEventCrossing*); struct Section { Section () @@ -75,11 +81,15 @@ private: Columns () { add (name); + add (s_start); + add (s_end); add (location); add (start); add (end); } Gtk::TreeModelColumn name; + Gtk::TreeModelColumn s_start; + Gtk::TreeModelColumn s_end; Gtk::TreeModelColumn location; Gtk::TreeModelColumn start; Gtk::TreeModelColumn end; @@ -89,8 +99,9 @@ private: Glib::RefPtr _model; Gtk::TreeView _view; Gtk::ScrolledWindow _scroller; + Gtk::Widget* _old_focus; - bool _ignore_redisplay; + bool _no_redisplay; sigc::connection _scroll_timeout; }; diff --git a/gtk2_ardour/location_ui.cc b/gtk2_ardour/location_ui.cc index 1515ae8343..15cafa9ac8 100644 --- a/gtk2_ardour/location_ui.cc +++ b/gtk2_ardour/location_ui.cc @@ -65,6 +65,7 @@ LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) , locate_to_end_button (_("Goto")) , length_clock (X_("locationlength"), true, "", true, false, true) , cd_check_button (_("CD")) + , section_check_button (_("Sect.")) , hide_check_button (_("Hide")) , lock_check_button (_("Lock")) , _clock_group (0) @@ -80,6 +81,7 @@ LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) name_label.set_name ("LocationEditNameLabel"); name_entry.set_name ("LocationEditNameEntry"); cd_check_button.set_name ("LocationEditCdButton"); + section_check_button.set_name ("LocationEditSectionButton"); hide_check_button.set_name ("LocationEditHideButton"); lock_check_button.set_name ("LocationEditLockButton"); isrc_label.set_name ("LocationEditNumberLabel"); @@ -164,6 +166,7 @@ LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) length_clock.ValueChanged.connect (sigc::bind ( sigc::mem_fun(*this, &LocationEditRow::clock_changed), LocLength)); cd_check_button.signal_toggled().connect(sigc::mem_fun(*this, &LocationEditRow::cd_toggled)); + section_check_button.signal_toggled().connect(sigc::mem_fun(*this, &LocationEditRow::section_toggled)); hide_check_button.signal_toggled().connect(sigc::mem_fun(*this, &LocationEditRow::hide_toggled)); lock_check_button.signal_toggled().connect(sigc::mem_fun(*this, &LocationEditRow::lock_toggled)); @@ -283,20 +286,21 @@ LocationEditRow::set_location (Location *loc) name_entry.show(); if (!cd_check_button.get_parent()) { - item_table.attach (cd_check_button, 4, 5, 0, 1, FILL, Gtk::AttachOptions (0), 4, 0); + item_table.attach (cd_check_button, 3, 4, 0, 1, FILL, Gtk::AttachOptions (0), 4, 0); + } + + if (!section_check_button.get_parent()) { + item_table.attach (section_check_button, 4, 5, 0, 1, FILL, Gtk::AttachOptions (0), 4, 0); } if (location->is_session_range()) { remove_button.set_sensitive (false); } - if (location->is_cue_marker()) { - cd_check_button.set_sensitive (false); - } + flags_changed (); - cd_check_button.set_active (location->is_cd_marker()); cd_check_button.show(); - + section_check_button.show(); hide_check_button.show(); lock_check_button.show(); } @@ -534,6 +538,15 @@ LocationEditRow::cd_toggled () } } +void +LocationEditRow::section_toggled () +{ + if (i_am_the_modifier || !location) { + return; + } + location->set_section (section_check_button.get_active()); +} + void LocationEditRow::hide_toggled () { @@ -667,8 +680,23 @@ LocationEditRow::flags_changed () i_am_the_modifier++; cd_check_button.set_active (location->is_cd_marker()); + section_check_button.set_active (location->is_section()); hide_check_button.set_active (location->is_hidden()); + if (location->is_cue_marker()) { + cd_check_button.set_sensitive (false); + section_check_button.set_sensitive (false); + } else if (location->is_section()) { + cd_check_button.set_sensitive (false); + section_check_button.set_sensitive (true); + } else if (location->is_cd_marker()) { + cd_check_button.set_sensitive (true); + section_check_button.set_sensitive (false); + } else { + cd_check_button.set_sensitive (true); + section_check_button.set_sensitive (true); + } + i_am_the_modifier--; } diff --git a/gtk2_ardour/location_ui.h b/gtk2_ardour/location_ui.h index 5d65bfef70..5c9368bc76 100644 --- a/gtk2_ardour/location_ui.h +++ b/gtk2_ardour/location_ui.h @@ -96,6 +96,7 @@ protected: AudioClock length_clock; Gtk::CheckButton cd_check_button; + Gtk::CheckButton section_check_button; Gtk::CheckButton hide_check_button; Gtk::CheckButton lock_check_button; @@ -131,6 +132,7 @@ protected: bool locate_to_clock (GdkEventButton*, AudioClock*); void cd_toggled (); + void section_toggled (); void hide_toggled (); void lock_toggled (); void remove_button_pressed ();