2 Copyright (C) 2004 Paul Davis
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <pbd/controllable.h>
26 #include <pbd/locale_guard.h>
28 #include "gtkmm2ext/gtk_ui.h"
29 #include "gtkmm2ext/utils.h"
30 #include "gtkmm2ext/keyboard.h"
31 #include "gtkmm2ext/barcontroller.h"
32 #include "gtkmm2ext/cairo_widget.h"
38 using namespace Gtkmm2ext;
40 BarController::BarController (Gtk::Adjustment& adj,
41 boost::shared_ptr<PBD::Controllable> mc)
42 : _slider (&adj, 60, 16)
43 , _logarithmic (false)
45 , _switch_on_release (false)
48 add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
49 set (.5, .5, 1.0, 1.0);
51 _slider.set_controllable (mc);
52 _slider.set_tweaks (PixFader::NoShowUnityLine);
54 _slider.StartGesture.connect (sigc::mem_fun(*this, &BarController::passtrhu_gesture_start));
55 _slider.StopGesture.connect (sigc::mem_fun(*this, &BarController::passtrhu_gesture_stop));
56 _slider.OnExpose.connect (sigc::mem_fun(*this, &BarController::before_expose));
57 _slider.set_name (get_name());
59 Gtk::SpinButton& spinner = _slider.get_spin_button();
60 spinner.signal_activate().connect (mem_fun (*this, &BarController::entry_activated));
61 spinner.signal_focus_out_event().connect (mem_fun (*this, &BarController::entry_focus_out));
62 spinner.signal_input().connect (mem_fun (*this, &BarController::entry_input));
63 spinner.signal_output().connect (mem_fun (*this, &BarController::entry_output));
64 spinner.set_digits (9);
65 spinner.set_numeric (true);
66 spinner.set_name ("BarControlSpinner");
71 BarController::~BarController ()
76 BarController::on_button_press_event (GdkEventButton* ev)
78 if (get_child() != &_slider) {
81 if (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
82 _switch_on_release = true;
85 _switch_on_release = false;
91 BarController::on_button_release_event (GdkEventButton* ev)
93 if (get_child() != &_slider) {
96 if (ev->button == 1 && _switch_on_release) {
97 Glib::signal_idle().connect (mem_fun (*this, &BarController::switch_to_spinner));
104 BarController::on_style_changed (const Glib::RefPtr<Gtk::Style>&)
106 _slider.set_name (get_name());
110 BarController::switch_to_bar ()
112 if (_switching || get_child() == &_slider) {
119 _slider.queue_draw ();
121 SpinnerActive (false); /* EMIT SIGNAL */
126 BarController::switch_to_spinner ()
128 if (_switching || get_child() != &_slider) {
133 Gtk::SpinButton& spinner = _slider.get_spin_button();
134 if (spinner.get_parent()) {
135 spinner.get_parent()->remove(spinner);
140 spinner.select_region (0, spinner.get_text_length());
141 spinner.grab_focus ();
143 SpinnerActive (true); /* EMIT SIGNAL */
148 BarController::entry_activated ()
154 BarController::entry_focus_out (GdkEventFocus* /*ev*/)
161 BarController::before_expose ()
164 _slider.set_text (get_label (xpos), false, false);
168 BarController::set_sensitive (bool yn)
170 Alignment::set_sensitive (yn);
171 _slider.set_sensitive (yn);
175 This is called when we need to update the adjustment with the value
176 from the spinner's text entry.
178 We need to use Gtk::Entry::get_text to avoid recursive nastiness :)
180 If we're not in logarithmic mode we can return false to use the
183 In theory we should check for conversion errors but set numeric
184 mode to true on the spinner prevents invalid input.
187 BarController::entry_input (double* new_value)
193 // extract a double from the string and take its log
194 Gtk::SpinButton& spinner = _slider.get_spin_button();
195 Entry *entry = dynamic_cast<Entry *>(&spinner);
199 // Switch to user's preferred locale so that
200 // if they use different LC_NUMERIC conventions,
201 // we will honor them.
203 PBD::LocaleGuard lg ("");
204 sscanf (entry->get_text().c_str(), "%lf", &value);
207 *new_value = log(value);
213 This is called when we need to update the spinner's text entry
214 with the value of the adjustment.
216 We need to use Gtk::Entry::set_text to avoid recursive nastiness :)
218 If we're not in logarithmic mode we can return false to use the
222 BarController::entry_output ()
229 Gtk::SpinButton& spinner = _slider.get_spin_button();
231 // generate the exponential and turn it into a string
232 // convert to correct locale.
238 // Switch to user's preferred locale so that
239 // if they use different LC_NUMERIC conventions,
240 // we will honor them.
242 PBD::LocaleGuard lg ("");
243 snprintf (buf, sizeof (buf), "%g", exp (spinner.get_adjustment()->get_value()));
246 Entry *entry = dynamic_cast<Entry *>(&spinner);
247 entry->set_text(buf);