From 1343f3370601637435ee2e98d7d2e6641ff53ef0 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 3 Jul 2016 22:24:57 +0200 Subject: add an ArdourButton/SpinButton Widget alternative to ArdourDisplay (dropdown) to provide numeric entry with ArdourKnob. --- gtk2_ardour/ardour_spinner.cc | 205 ++++++++++++++++++++++++++++++++++++++++++ gtk2_ardour/ardour_spinner.h | 72 +++++++++++++++ gtk2_ardour/wscript | 1 + 3 files changed, 278 insertions(+) create mode 100644 gtk2_ardour/ardour_spinner.cc create mode 100644 gtk2_ardour/ardour_spinner.h (limited to 'gtk2_ardour') diff --git a/gtk2_ardour/ardour_spinner.cc b/gtk2_ardour/ardour_spinner.cc new file mode 100644 index 0000000000..94c1a25d8f --- /dev/null +++ b/gtk2_ardour/ardour_spinner.cc @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2016 Robin Gareus + * Copyright (C) 2011 Paul Davis + * + * 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 "gtkmm2ext/gui_thread.h" +#include "gtkmm2ext/keyboard.h" + +#include "ardour_spinner.h" + +using namespace ARDOUR; + +ArdourSpinner::ArdourSpinner ( + boost::shared_ptr c, + Gtk::Adjustment* adj, + boost::shared_ptr p) + : _btn (ArdourButton::Text) + , _ctrl_adj (adj) + , _spin_adj (0, c->lower (), c->upper (), .1, .01) + , _spinner (_spin_adj) + , _switching (false) + , _switch_on_release (false) + , _ctrl_ignore (false) + , _spin_ignore (false) + , _controllable (c) + , _printer (p) +{ + add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); + set (.5, .5, 1.0, 1.0); + set_border_width (0); + + _btn.set_controllable (c); + _btn.set_fallthrough_to_parent (true); + + _spinner.signal_activate().connect (mem_fun (*this, &ArdourSpinner::entry_activated)); + _spinner.signal_focus_out_event().connect (mem_fun (*this, &ArdourSpinner::entry_focus_out)); + _spinner.set_digits (4); + _spinner.set_numeric (true); + _spinner.set_name ("BarControlSpinner"); + + _spin_adj.set_step_increment(c->interface_to_internal(_ctrl_adj->get_step_increment()) - c->lower ()); + _spin_adj.set_page_increment(c->interface_to_internal(_ctrl_adj->get_page_increment()) - c->lower ()); + + _spin_adj.signal_value_changed().connect (sigc::mem_fun(*this, &ArdourSpinner::spin_adjusted)); + adj->signal_value_changed().connect (sigc::mem_fun(*this, &ArdourSpinner::ctrl_adjusted)); + c->Changed.connect (watch_connection, invalidator(*this), boost::bind (&ArdourSpinner::controllable_changed, this), gui_context()); + + add (_btn); + show_all (); + + controllable_changed(); + ctrl_adjusted (); +} + + +ArdourSpinner::~ArdourSpinner () +{ +} + +bool +ArdourSpinner::on_button_press_event (GdkEventButton* ev) +{ + if (get_child() != &_btn) { + return false; + } + + if (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) { + _switch_on_release = true; + return true; + } else { + _switch_on_release = false; + } + return false; +} + +bool +ArdourSpinner::on_button_release_event (GdkEventButton* ev) +{ + if (get_child() != &_btn) { + return false; + } + if (ev->button == 1 && _switch_on_release) { + Glib::signal_idle().connect (mem_fun (*this, &ArdourSpinner::switch_to_spinner)); + return true; + } + return false; +} + +bool +ArdourSpinner::on_scroll_event (GdkEventScroll* ev) +{ + float scale = 1.0; + if (ev->state & Gtkmm2ext::Keyboard::GainFineScaleModifier) { + if (ev->state & Gtkmm2ext::Keyboard::GainExtraFineScaleModifier) { + scale *= 0.01; + } else { + scale *= 0.10; + } + } + + boost::shared_ptr c = _btn.get_controllable(); + if (c) { + float val = c->get_interface(); + + if ( ev->direction == GDK_SCROLL_UP ) + val += 0.05 * scale; //by default, we step in 1/20ths of the knob travel + else + val -= 0.05 * scale; + + c->set_interface(val); + } + + return true; +} + +gint +ArdourSpinner::switch_to_button () +{ + if (_switching || get_child() == &_btn) { + return false; + } + _switching = true; + remove (); + add (_btn); + _btn.show (); + _btn.set_dirty (); + _switching = false; + return false; +} + +gint +ArdourSpinner::switch_to_spinner () +{ + if (_switching || get_child() != &_btn) { + return false; + } + _switching = true; + remove (); + add (_spinner); + _spinner.show (); + _spinner.select_region (0, _spinner.get_text_length ()); + _spinner.grab_focus (); + _switching = false; + return false; +} + +void +ArdourSpinner::entry_activated () +{ + switch_to_button (); +} + +bool +ArdourSpinner::entry_focus_out (GdkEventFocus* /*ev*/) +{ + entry_activated (); + return true; +} + +void +ArdourSpinner::ctrl_adjusted () +{ + if (_spin_ignore) { + return; + } + _ctrl_ignore = true; + _spin_adj.set_value (_controllable->interface_to_internal (_ctrl_adj->get_value ())); + _ctrl_ignore = false; +} + +void +ArdourSpinner::spin_adjusted () +{ + if (_ctrl_ignore) { + return; + } + _spin_ignore = true; + _ctrl_adj->set_value (_controllable->internal_to_interface (_spin_adj.get_value ())); + _spin_ignore = false; +} + +void +ArdourSpinner::controllable_changed () +{ + if (_printer) { + _btn.set_text (_printer->value_as_string (_controllable)); + } else { + _btn.set_text (_controllable->get_user_string()); + } + _btn.set_dirty(); +} diff --git a/gtk2_ardour/ardour_spinner.h b/gtk2_ardour/ardour_spinner.h new file mode 100644 index 0000000000..de8c9a147a --- /dev/null +++ b/gtk2_ardour/ardour_spinner.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016 Robin Gareus + * Copyright (C) 2011 Paul Davis + * + * 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 +#ifndef __gtk2_ardour_ardour_spinner_h__ +#define __gtk2_ardour_ardour_spinner_h__ + +#include + +#include "ardour/automatable.h" +#include "ardour/automation_control.h" +#include "ardour_button.h" + +class ArdourSpinner : public Gtk::Alignment +{ + public: + ArdourSpinner ( + boost::shared_ptr, + Gtk::Adjustment* adj, + boost::shared_ptr); + + virtual ~ArdourSpinner (); + + protected: + bool on_button_press_event (GdkEventButton*); + bool on_button_release_event (GdkEventButton*); + bool on_scroll_event (GdkEventScroll* ev); + + void controllable_changed (); + PBD::ScopedConnection watch_connection; + + private: + + bool entry_focus_out (GdkEventFocus*); + void entry_activated (); + gint switch_to_button (); + gint switch_to_spinner (); + + void ctrl_adjusted(); + void spin_adjusted(); + + ArdourButton _btn; + Gtk::Adjustment* _ctrl_adj; + Gtk::Adjustment _spin_adj; + Gtk::SpinButton _spinner; + bool _switching; + bool _switch_on_release; + bool _ctrl_ignore; + bool _spin_ignore; + + boost::shared_ptr _controllable; + boost::shared_ptr _printer; + +}; + +#endif /* __gtk2_ardour_ardour_menu_h__ */ diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index d55945087b..fe73f79a94 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -36,6 +36,7 @@ gtk2_ardour_sources = [ 'ardour_display.cc', 'ardour_dropdown.cc', 'ardour_knob.cc', + 'ardour_spinner.cc', 'ardour_ui.cc', 'ardour_ui2.cc', 'ardour_ui_dependents.cc', -- cgit v1.2.3