X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Ffloating_text_entry.cc;h=e22e77982c493916495eea39c658ba7100d75906;hb=99de9ac6decbd24359581a6bd38939837efc9866;hp=9907360c014d2b9c3af777639cf731fbe77ac085;hpb=4dc63966f0872efe768dad61eb9b8785d06b92d1;p=ardour.git diff --git a/gtk2_ardour/floating_text_entry.cc b/gtk2_ardour/floating_text_entry.cc index 9907360c01..e22e77982c 100644 --- a/gtk2_ardour/floating_text_entry.cc +++ b/gtk2_ardour/floating_text_entry.cc @@ -25,26 +25,34 @@ #include "gtkmm2ext/doi.h" #include "gtkmm2ext/utils.h" -#include "i18n.h" +#include "pbd/i18n.h" -FloatingTextEntry::FloatingTextEntry (const std::string& initial_contents) - : Gtk::Window (Gtk::WINDOW_POPUP) - , entry_changed (false) +FloatingTextEntry::FloatingTextEntry (Gtk::Window* parent, const std::string& initial_contents) + : Gtk::Window () + , entry_changed (false) { - set_name (X_("FloatingTextEntry")); + //set_name (X_("FloatingTextEntry")); set_position (Gtk::WIN_POS_MOUSE); set_border_width (0); - + set_type_hint(Gdk::WINDOW_TYPE_HINT_POPUP_MENU); + set_resizable (false); + if (!initial_contents.empty()) { entry.set_text (initial_contents); } entry.show (); - entry.signal_changed().connect (sigc::mem_fun (*this, &FloatingTextEntry::changed)); - entry.signal_activate().connect (sigc::mem_fun (*this, &FloatingTextEntry::activated)); - entry.signal_key_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::key_press)); - entry.signal_button_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::button_press)); - PublicEditor::instance ().signal_focus_out_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::entry_focus_out)); + _connections.push_back (entry.signal_changed().connect (sigc::mem_fun (*this, &FloatingTextEntry::changed))); + _connections.push_back (entry.signal_activate().connect (sigc::mem_fun (*this, &FloatingTextEntry::activated))); + _connections.push_back (entry.signal_key_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::key_press), false)); + _connections.push_back (entry.signal_key_release_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::key_release), false)); + _connections.push_back (entry.signal_button_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::button_press))); + + entry.select_region (0, -1); + + if (parent) { + set_transient_for (*parent); + } add (entry); } @@ -60,6 +68,7 @@ FloatingTextEntry::on_realize () { Gtk::Window::on_realize (); get_window()->set_decorations (Gdk::WMDecoration (0)); + set_keep_above (true); entry.add_modal_grab (); } @@ -68,10 +77,11 @@ FloatingTextEntry::entry_focus_out (GdkEventFocus* ev) { entry.remove_modal_grab (); if (entry_changed) { - use_text (entry.get_text ()); + disconect_signals (); + use_text (entry.get_text (), 0); /* EMIT SIGNAL */ } - delete_when_idle ( this); + idle_delete_self (); return false; } @@ -89,10 +99,11 @@ FloatingTextEntry::button_press (GdkEventButton* ev) Glib::signal_idle().connect (sigc::bind_return (sigc::bind (sigc::ptr_fun (gtk_main_do_event), gdk_event_copy ((GdkEvent*) ev)), false)); if (entry_changed) { - use_text (entry.get_text ()); + disconect_signals (); + use_text (entry.get_text (), 0); /* EMIT SIGNAL */ } - delete_when_idle ( this); + idle_delete_self (); return false; } @@ -100,34 +111,98 @@ FloatingTextEntry::button_press (GdkEventButton* ev) void FloatingTextEntry::activated () { - use_text (entry.get_text()); // EMIT SIGNAL - delete_when_idle (this); + disconect_signals (); + use_text (entry.get_text(), 0); // EMIT SIGNAL + idle_delete_self (); } bool FloatingTextEntry::key_press (GdkEventKey* ev) { + /* steal escape, tabs from GTK */ + switch (ev->keyval) { case GDK_Escape: - delete_when_idle (this); + case GDK_ISO_Left_Tab: + case GDK_Tab: + return true; + } + return false; +} + +bool +FloatingTextEntry::key_release (GdkEventKey* ev) +{ + switch (ev->keyval) { + case GDK_Escape: + /* cancel edit */ + idle_delete_self (); + return true; + + case GDK_ISO_Left_Tab: + /* Shift+Tab Keys Pressed. Note that for Shift+Tab, GDK actually + * generates a different ev->keyval, rather than setting + * ev->state. + */ + disconect_signals (); + use_text (entry.get_text(), -1); // EMIT SIGNAL, move to prev + idle_delete_self (); + return true; + + case GDK_Tab: + disconect_signals (); + use_text (entry.get_text(), 1); // EMIT SIGNAL, move to next + idle_delete_self (); return true; - break; default: break; } + return false; } + void FloatingTextEntry::on_hide () { entry.remove_modal_grab (); /* No hide button is shown (no decoration on the window), - so being hidden is equivalent to the Escape key or any other - method of cancelling the edit. - */ + * so being hidden is equivalent to the Escape key or any other + * method of cancelling the edit. + * + * This is also used during disconect_signals() before calling + * use_text (). see note below. + * + * If signals are already disconnected, idle-delete must be + * in progress already. + */ + if (!_connections.empty ()) { + idle_delete_self (); + } + Gtk::Window::on_hide (); +} +void +FloatingTextEntry::disconect_signals () +{ + for (std::list::iterator i = _connections.begin(); i != _connections.end(); ++i) { + i->disconnect (); + } + _connections.clear (); + /* the entry is floating on-top, emitting use_text() + * may result in another dialog being shown (cannot rename track) + * which would + * - be stacked below the floating text entry + * - return focus to the entry when closedA + * so we hide the entry here. + */ + hide (); +} + +void +FloatingTextEntry::idle_delete_self () +{ + disconect_signals (); delete_when_idle (this); - Gtk::Window::on_hide (); }