diff --git a/gtk2_ardour/foldback_strip.cc b/gtk2_ardour/foldback_strip.cc index f88d670852..6b96eb3261 100644 --- a/gtk2_ardour/foldback_strip.cc +++ b/gtk2_ardour/foldback_strip.cc @@ -630,7 +630,6 @@ FoldbackStrip::set_route (std::shared_ptr rt) /* now force an update of all the various elements */ name_changed (); update_send_box (); - comment_changed (); connect_to_pan (); _panners.setup_pan (); _panners.show_all (); diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index b04d7423ee..c6eda847e7 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -175,9 +175,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session* sess, std::shared_ptr rt, if (is_master () && !_route->comment().empty () && _session->config.get_show_master_bus_comment_on_load () && self_destruct) { open_comment_editor (); - _comment_window->hide (); - _comment_window->set_position (Gtk::WIN_POS_CENTER_ON_PARENT); - _comment_window->present (); /* show only once */ _session->config.set_show_master_bus_comment_on_load (false); } @@ -725,7 +722,6 @@ MixerStrip::set_route (std::shared_ptr rt) /* now force an update of all the various elements */ name_changed (); - comment_changed (); route_group_changed (); update_track_number_visibility (); diff --git a/gtk2_ardour/route_comment_editor.cc b/gtk2_ardour/route_comment_editor.cc new file mode 100644 index 0000000000..228ea5eab2 --- /dev/null +++ b/gtk2_ardour/route_comment_editor.cc @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2025 Robin Gareus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "pbd/compose.h" +#include "pbd/unwind.h" + +#include "ardour/session.h" +#include "ardour/session_configuration.h" + +#include "gtkmm2ext/utils.h" + +#include "gui_thread.h" +#include "option_editor.h" +#include "route_comment_editor.h" +#include "ui_config.h" + +#include "pbd/i18n.h" + +using namespace Gtk; +using namespace ARDOUR; + +RouteCommentEditor::RouteCommentEditor () + : ArdourWindow ("") + , _bo (nullptr) + , _ignore_change (false) +{ + const float scale = std::max (1.f, UIConfiguration::instance ().get_ui_scale ()); + set_default_size (400 * scale, 200 * scale); + + set_skip_taskbar_hint (true); + + _comment_area.set_name ("MixerTrackCommentArea"); + _comment_area.set_wrap_mode (WRAP_WORD); + _comment_area.set_editable (true); + + add (_vbox); + + signal_hide ().connect (sigc::mem_fun (*this, &RouteCommentEditor::commit_change)); + _comment_area.get_buffer ()->signal_changed ().connect (sigc::mem_fun (*this, &RouteCommentEditor::commit_change)); +} + +RouteCommentEditor::~RouteCommentEditor () +{ + reset (); +} + +void +RouteCommentEditor::reset () +{ + hide (); + delete _bo; + _bo = nullptr; + if (_route && _route->comment_editor () == this) { + _route->set_comment_editor (nullptr); + } + _route.reset (); + _connections.drop_connections (); +} + +void +RouteCommentEditor::toggle (std::shared_ptr r) +{ + if (r && r->comment_editor ()) { + ArdourWindow* self = r->comment_editor (); + if (self->get_visible ()) { + self->hide (); + } else { + self->present (); + } + return; + } + open (r); +} + +void +RouteCommentEditor::open (std::shared_ptr r) +{ + if (r && r->comment_editor ()) { + r->comment_editor ()->present (); + return; + } + if (_route == r) { + present (); + return; + } + if (!r) { + assert (0); + reset (); + return; + } + _route = r; + _route->set_comment_editor (this); + _route->comment_changed.connect (_connections, invalidator (*this), std::bind (&RouteCommentEditor::comment_changed, this), gui_context ()); + _route->DropReferences.connect (_connections, invalidator (*this), std::bind (&RouteCommentEditor::reset, this), gui_context ()); + + set_title (string_compose ("%1: %2", _route->name (), _ (": comment editor"))); + _comment_area.get_buffer ()->set_text (_route->comment ()); + + Gtkmm2ext::container_clear (_vbox, false); + _vbox.pack_start (_comment_area); + + delete _bo; + if (_route->is_master ()) { + ARDOUR::Session* session = &_route->session (); + _bo = new BoolOption ( + "show-master-bus-comment-on-load", + _ ("Show this comment on next session load"), + sigc::mem_fun (session->config, &SessionConfiguration::get_show_master_bus_comment_on_load), + sigc::mem_fun (session->config, &SessionConfiguration::set_show_master_bus_comment_on_load)); + + _vbox.pack_start (_bo->tip_widget (), false, false, 4); + _bo->tip_widget ().show_all (); + _bo->parameter_changed ("show-master-bus-comment-on-load"); + session->config.ParameterChanged.connect (_connections, invalidator (*this), std::bind (&BoolOption::parameter_changed, _bo, _1), gui_context ()); + } else { + _bo = nullptr; + } + + _vbox.show_all (); + set_position (Gtk::WIN_POS_CENTER_ON_PARENT); + present (); +} + +void +RouteCommentEditor::comment_changed () +{ + PBD::Unwinder uw (_ignore_change, true); + _comment_area.get_buffer ()->set_text (_route->comment ()); +} + +void +RouteCommentEditor::commit_change () +{ + if (!_route || _ignore_change) { + return; + } + + std::string const str = _comment_area.get_buffer ()->get_text (); + if (str != _route->comment ()) { + _route->set_comment (str, this); + } +} diff --git a/gtk2_ardour/route_comment_editor.h b/gtk2_ardour/route_comment_editor.h new file mode 100644 index 0000000000..78b0c17c81 --- /dev/null +++ b/gtk2_ardour/route_comment_editor.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2025 Robin Gareus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +#include +#include + +#include "ardour/route.h" + +#include "ardour_window.h" + +class BoolOption; + +class RouteCommentEditor : public ArdourWindow +{ +public: + RouteCommentEditor (); + ~RouteCommentEditor (); + + void reset (); + void toggle (std::shared_ptr); + void open (std::shared_ptr); + +private: + void comment_changed (); + void commit_change (); + + Gtk::TextView _comment_area; + Gtk::VBox _vbox; + BoolOption* _bo; + bool _ignore_change; + + std::shared_ptr _route; + PBD::ScopedConnectionList _connections; +}; diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 859ae7929f..010890526c 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -76,7 +76,6 @@ #include "keyboard.h" #include "mixer_strip.h" #include "mixer_ui.h" -#include "option_editor.h" #include "opts.h" #include "patch_change_widget.h" #include "playlist_selector.h" @@ -128,10 +127,8 @@ RouteUI::RouteUI (ARDOUR::Session* sess) , solo_menu(0) , sends_menu(0) , playlist_action_menu (0) - , _comment_window(0) , _playlist_selector(0) , _record_menu(0) - , _comment_area(0) , _invert_menu(0) { if (program_port_prefix.empty()) { @@ -168,7 +165,6 @@ RouteUI::~RouteUI() delete monitor_disk_button; delete playlist_action_menu; delete _record_menu; - delete _comment_window; delete _invert_menu; delete _playlist_selector; @@ -199,7 +195,6 @@ RouteUI::init () denormal_menu_item = 0; _step_edit_item = 0; _rec_safe_item = 0; - _ignore_comment_edit = false; _i_am_the_modifier = 0; _n_polarity_invert = 0; @@ -390,8 +385,6 @@ RouteUI::set_route (std::shared_ptr rp) _route->active_changed.connect (route_connections, invalidator (*this), std::bind (&RouteUI::route_active_changed, this), gui_context()); - _route->comment_changed.connect (route_connections, invalidator (*this), std::bind (&RouteUI::comment_changed, this), gui_context()); - _route->mute_control()->Changed.connect (route_connections, invalidator (*this), std::bind (&RouteUI::update_mute_display, this), gui_context()); _route->solo_control()->Changed.connect (route_connections, invalidator (*this), std::bind (&RouteUI::update_solo_display, this), gui_context()); _route->solo_safe_control()->Changed.connect (route_connections, invalidator (*this), std::bind (&RouteUI::update_solo_display, this), gui_context()); @@ -1755,89 +1748,14 @@ RouteUI::route_rename () void RouteUI::toggle_comment_editor () { - if (_comment_window && _comment_window->get_visible ()) { - _comment_window->hide (); - } else { - open_comment_editor (); - } + _comment_editor.toggle (_route); } void RouteUI::open_comment_editor () { - if (_comment_window == 0) { - setup_comment_editor (); - } - - string title; - title = _route->name(); - title += _(": comment editor"); - - _comment_window->set_title (title); - _comment_window->present(); -} - -void -RouteUI::setup_comment_editor () -{ - const float scale = std::max(1.f, UIConfiguration::instance().get_ui_scale()); - - _comment_window = new ArdourWindow (""); // title will be reset to show route - _comment_window->set_skip_taskbar_hint (true); - _comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing)); - _comment_window->set_default_size (400 * scale, 200 * scale); - - VBox* vbox = manage (new VBox ()); - vbox->show (); - - _comment_area = manage (new TextView()); - _comment_area->set_name ("MixerTrackCommentArea"); - _comment_area->set_wrap_mode (WRAP_WORD); - _comment_area->set_editable (true); - _comment_area->get_buffer()->set_text (_route->comment()); - _comment_area->show (); - - vbox->pack_start (*_comment_area); - - if (is_master ()) { - BoolOption* bo = new BoolOption ( - "show-master-bus-comment-on-load", - _("Show this comment on next session load"), - sigc::mem_fun (_session->config, &SessionConfiguration::get_show_master_bus_comment_on_load), - sigc::mem_fun (_session->config, &SessionConfiguration::set_show_master_bus_comment_on_load) - ); - - vbox->pack_start (bo->tip_widget (), false, false, 4); - bo->tip_widget ().show_all (); - bo->parameter_changed ("show-master-bus-comment-on-load"); - vbox->signal_unrealize().connect ([bo]() { delete bo; }); - _session->config.ParameterChanged.connect (*this, invalidator (*this), std::bind (&BoolOption::parameter_changed, bo, _1), gui_context()); - } - _comment_window->add (*vbox); -} - -void -RouteUI::comment_changed () -{ - _ignore_comment_edit = true; - if (_comment_area) { - _comment_area->get_buffer()->set_text (_route->comment()); - } - _ignore_comment_edit = false; -} - -void -RouteUI::comment_editor_done_editing () -{ - ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src) - - string const str = _comment_area->get_buffer()->get_text(); - if (str == _route->comment ()) { - return; - } - - _route->set_comment (str, this); + _comment_editor.open (_route); } void diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h index cafa010782..323d4094f0 100644 --- a/gtk2_ardour/route_ui.h +++ b/gtk2_ardour/route_ui.h @@ -45,6 +45,7 @@ #include "ardour/track.h" #include "axis_view.h" +#include "route_comment_editor.h" #include "selectable.h" #include "stripable_colorpicker.h" #include "window_manager.h" @@ -155,7 +156,6 @@ public: void update_monitoring_display (); void open_comment_editor (); void toggle_comment_editor (); - void comment_changed (); void set_route_active (bool, bool); void set_disk_io_point (ARDOUR::DiskIOPoint); void fan_out (bool to_busses = true, bool group = true); @@ -269,8 +269,6 @@ protected: ARDOUR::SoloMuteRelease* _solo_release; ARDOUR::SoloMuteRelease* _mute_release; - ArdourWindow* _comment_window; - private: void invert_menu_toggled (uint32_t); bool invert_press (GdkEventButton*); @@ -293,9 +291,6 @@ private: void step_edit_changed (bool); void toggle_rec_safe (); - void setup_comment_editor (); - void comment_editor_done_editing (); - void init_mute_menu (ARDOUR::MuteMaster::MutePoint, Gtk::CheckMenuItem*); void build_mute_menu (); void build_solo_menu (); @@ -325,12 +320,10 @@ private: PlaylistSelector* _playlist_selector; Gtk::Menu* _record_menu; - Gtk::TextView* _comment_area; Gtk::CheckMenuItem* _step_edit_item; Gtk::CheckMenuItem* _rec_safe_item; - bool _ignore_comment_edit; int _i_am_the_modifier; Gtk::Menu* _invert_menu; uint32_t _n_polarity_invert; @@ -338,6 +331,7 @@ private: std::vector _invert_buttons; StripableColorDialog _color_picker; + RouteCommentEditor _comment_editor; sigc::connection send_blink_connection; sigc::connection rec_blink_connection; diff --git a/gtk2_ardour/surround_strip.cc b/gtk2_ardour/surround_strip.cc index efffa7a27e..9e5f49e828 100644 --- a/gtk2_ardour/surround_strip.cc +++ b/gtk2_ardour/surround_strip.cc @@ -313,7 +313,6 @@ SurroundStrip::set_route (std::shared_ptr r) /* now force an update of all the various elements */ name_changed (); - comment_changed (); setup_comment_button (); add_events (Gdk::BUTTON_RELEASE_MASK); diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 0f947ee21a..1d9889aaab 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -259,6 +259,7 @@ gtk2_ardour_sources = [ 'region_view.cc', 'return_ui.cc', 'rhythm_ferret.cc', + 'route_comment_editor.cc', 'route_group_dialog.cc', 'route_group_menu.cc', 'route_list_base.cc',