tweak appearance of a FaderOption in the option editor(s)
[ardour.git] / gtk2_ardour / option_editor.h
1 /*
2     Copyright (C) 2009 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __gtk_ardour_option_editor_h__
21 #define __gtk_ardour_option_editor_h__
22
23 #include <gtkmm/notebook.h>
24 #include <gtkmm/checkbutton.h>
25 #include <gtkmm/comboboxtext.h>
26 #include <gtkmm/spinbutton.h>
27 #include <gtkmm/table.h>
28 #include "gtkmm2ext/slider_controller.h"
29 #include "ardour_window.h"
30 #include "audio_clock.h"
31 #include "ardour/types.h"
32
33 /** @file option_editor.h
34  *  @brief Base class for option editing dialog boxes.
35  *
36  *  Code to provided the basis for dialogs which allow the user to edit options
37  *  from an ARDOUR::Configuration class.
38  *
39  *  The idea is that we have an OptionEditor class which is the dialog box.
40  *  This is essentially a GTK Notebook.  OptionEditorComponent objects can
41  *  then be added to the OptionEditor, and these components are arranged on
42  *  the pages of the Notebook.  There is also an OptionEditorComponent hierarchy
43  *  here, providing things like boolean and combobox option components.
44  *
45  *  It is intended that OptionEditor be subclassed to implement a particular
46  *  options dialog.
47  */
48
49 namespace ARDOUR {
50         class Configuration;
51 }
52
53 class OptionEditorPage;
54
55 /** Base class for components of an OptionEditor dialog */
56 class OptionEditorComponent
57 {
58 public:
59         virtual ~OptionEditorComponent() {}
60
61         /** Called when a configuration parameter's value has changed.
62          *  @param p parameter name
63          */
64         virtual void parameter_changed (std::string const & p) = 0;
65
66         /** Called to instruct the object to set its UI state from the configuration */
67         virtual void set_state_from_config () = 0;
68
69         /** Called to instruct the object to add itself to an OptionEditorPage */
70         virtual void add_to_page (OptionEditorPage *) = 0;
71
72         void add_widget_to_page (OptionEditorPage*, Gtk::Widget*);
73         void add_widgets_to_page (OptionEditorPage*, Gtk::Widget*, Gtk::Widget*);
74
75         void set_note (std::string const &);
76
77 private:
78         void maybe_add_note (OptionEditorPage *, int);
79         
80         std::string _note;
81 };
82
83 /** A component which provides a subheading within the dialog */
84 class OptionEditorHeading : public OptionEditorComponent
85 {
86 public:
87         OptionEditorHeading (std::string const &);
88
89         void parameter_changed (std::string const &) {}
90         void set_state_from_config () {}
91         void add_to_page (OptionEditorPage *);
92
93 private:
94         Gtk::Label* _label; ///< the label used for the heading
95 };
96
97 /** A component which provides a box into which a subclass can put arbitrary widgets */
98 class OptionEditorBox : public OptionEditorComponent
99 {
100 public:
101
102         /** Construct an OpenEditorBox */
103         OptionEditorBox ()
104         {
105                 _box = Gtk::manage (new Gtk::VBox);
106                 _box->set_spacing (4);
107         }
108
109         void parameter_changed (std::string const &) = 0;
110         void set_state_from_config () = 0;
111         void add_to_page (OptionEditorPage *);
112
113 protected:
114
115         Gtk::VBox* _box; ///< constituent box for subclasses to add widgets to
116 };
117
118 /** Base class for components which provide UI to change an option */
119 class Option : public OptionEditorComponent
120 {
121 public:
122         /** Construct an Option.
123          *  @param i Option id (e.g. "plugins-stop-with-transport")
124          *  @param n User-visible name (e.g. "Stop plugins when the transport is stopped")
125          */
126         Option (std::string const & i,
127                 std::string const & n
128                 )
129                 : _id (i),
130                   _name (n)
131         {}
132
133         void parameter_changed (std::string const & p)
134         {
135                 if (p == _id) {
136                         set_state_from_config ();
137                 }
138         }
139
140         virtual void set_state_from_config () = 0;
141         virtual void add_to_page (OptionEditorPage*) = 0;
142
143         std::string id () const {
144                 return _id;
145         }
146
147 protected:
148
149         std::string _id;
150         std::string _name;
151 };
152
153 /** Component which provides the UI to handle a boolean option using a GTK CheckButton */
154 class BoolOption : public Option
155 {
156 public:
157
158         BoolOption (std::string const &, std::string const &, sigc::slot<bool>, sigc::slot<bool, bool>);
159         void set_state_from_config ();
160         void add_to_page (OptionEditorPage*);
161
162         void set_sensitive (bool yn) {
163                 _button->set_sensitive (yn);
164         }
165
166 private:
167
168         void toggled ();
169
170         sigc::slot<bool> _get; ///< slot to get the configuration variable's value
171         sigc::slot<bool, bool> _set;  ///< slot to set the configuration variable's value
172         Gtk::CheckButton* _button; ///< UI button
173 };
174
175 /** Component which provides the UI to handle a string option using a GTK Entry */
176 class EntryOption : public Option
177 {
178 public:
179
180         EntryOption (std::string const &, std::string const &, sigc::slot<std::string>, sigc::slot<bool, std::string>);
181         void set_state_from_config ();
182         void add_to_page (OptionEditorPage*);
183
184 private:
185
186         void activated ();
187
188         sigc::slot<std::string> _get; ///< slot to get the configuration variable's value
189         sigc::slot<bool, std::string> _set;  ///< slot to set the configuration variable's value
190         Gtk::Label* _label; ///< UI label
191         Gtk::Entry* _entry; ///< UI entry
192 };
193
194
195 /** Component which provides the UI to handle an enumerated option using a GTK CheckButton.
196  *  The template parameter is the enumeration.
197  */
198 template <class T>
199 class ComboOption : public Option
200 {
201 public:
202
203         /** Construct an ComboOption.
204          *  @param i id
205          *  @param n User-visible name.
206          *  @param g Slot to get the variable's value.
207          *  @param s Slot to set the variable's value.
208          */
209         ComboOption (
210                 std::string const & i,
211                 std::string const & n,
212                 sigc::slot<T> g,
213                 sigc::slot<bool, T> s
214                 )
215                 : Option (i, n),
216                   _get (g),
217                   _set (s)
218         {
219                 _label = manage (new Gtk::Label (n + ":"));
220                 _label->set_alignment (0, 0.5);
221                 _combo = manage (new Gtk::ComboBoxText);
222                 _combo->signal_changed().connect (sigc::mem_fun (*this, &ComboOption::changed));
223         }
224
225         void set_state_from_config () {
226                 uint32_t r = 0;
227                 while (r < _options.size() && _get () != _options[r]) {
228                         ++r;
229                 }
230
231                 if (r < _options.size()) {
232                         _combo->set_active (r);
233                 }
234         }
235
236         void add_to_page (OptionEditorPage* p)
237         {
238                 add_widgets_to_page (p, _label, _combo);
239         }
240
241         /** Add an allowed value for this option.
242          *  @param e Enumeration.
243          *  @param o User-visible name for this value.
244          */
245         void add (T e, std::string const & o) {
246                 _options.push_back (e);
247                 _combo->append_text (o);
248         }
249
250         void clear () {
251                 _combo->clear_items();
252                 _options.clear ();
253         }
254
255         void changed () {
256                 uint32_t const r = _combo->get_active_row_number ();
257                 if (r < _options.size()) {
258                         _set (_options[r]);
259                 }
260         }
261
262         void set_sensitive (bool yn) {
263                 _combo->set_sensitive (yn);
264         }
265
266 private:
267
268         sigc::slot<T> _get;
269         sigc::slot<bool, T> _set;
270         Gtk::Label* _label;
271         Gtk::ComboBoxText* _combo;
272         std::vector<T> _options;
273 };
274
275
276 /** Component which provides the UI to handle an numeric option using a GTK SpinButton */
277 template <class T>
278 class SpinOption : public Option
279 {
280 public:
281         /** Construct an SpinOption.
282          *  @param i id
283          *  @param n User-visible name.
284          *  @param g Slot to get the variable's value.
285          *  @param s Slot to set the variable's value.
286          *  @param min Variable minimum value.
287          *  @param max Variable maximum value.
288          *  @param step Step for the spin button.
289          *  @param page Page step for the spin button.
290          *  @param unit Unit name.
291          *  @param scale Scaling factor (such that for a value x in the spinbutton, x * scale is written to the config)
292          */
293         SpinOption (
294                 std::string const & i,
295                 std::string const & n,
296                 sigc::slot<T> g,
297                 sigc::slot<bool, T> s,
298                 T min,
299                 T max,
300                 T step,
301                 T page,
302                 std::string const & unit = "",
303                 float scale = 1
304                 )
305                 : Option (i, n),
306                   _get (g),
307                   _set (s),
308                   _scale (scale)
309         {
310                 _label = manage (new Gtk::Label (n + ":"));
311                 _label->set_alignment (0, 0.5);
312
313                 _spin = manage (new Gtk::SpinButton);
314                 _spin->set_range (min, max);
315                 _spin->set_increments (step, page);
316
317                 _box = manage (new Gtk::HBox);
318                 _box->pack_start (*_spin, true, true);
319                 _box->set_spacing (4);
320                 if (unit.length()) {
321                         _box->pack_start (*manage (new Gtk::Label (unit)), false, false);
322                 }
323
324                 _spin->signal_value_changed().connect (sigc::mem_fun (*this, &SpinOption::changed));
325         }
326
327         void set_state_from_config ()
328         {
329                 _spin->set_value (_get () / _scale);
330         }
331
332         void add_to_page (OptionEditorPage* p)
333         {
334                 add_widgets_to_page (p, _label, _box);
335         }
336
337         void changed ()
338         {
339                 _set (static_cast<T> (_spin->get_value ()) * _scale);
340         }
341
342 private:
343         sigc::slot<T> _get;
344         sigc::slot<bool, T> _set;
345         float _scale;
346         Gtk::Label* _label;
347         Gtk::HBox* _box;
348         Gtk::SpinButton* _spin;
349 };
350
351 class FaderOption : public Option
352 {
353 public:
354
355         FaderOption (std::string const &, std::string const &, sigc::slot<ARDOUR::gain_t> g, sigc::slot<bool, ARDOUR::gain_t> s);
356         void set_state_from_config ();
357         void add_to_page (OptionEditorPage *);
358
359 private:
360         void db_changed ();
361
362         Gtk::Adjustment _db_adjustment;
363         Gtkmm2ext::HSliderController* _db_slider;
364         Glib::RefPtr<Gdk::Pixbuf> _pix;
365         Gtk::Entry _db_display;
366         Gtk::Label _label;
367         Gtk::HBox _box;
368         Gtk::VBox _fader_centering_box;
369         sigc::slot<ARDOUR::gain_t> _get;
370         sigc::slot<bool, ARDOUR::gain_t> _set;
371 };
372
373 class ClockOption : public Option
374 {
375 public:
376         ClockOption (std::string const &, std::string const &, sigc::slot<ARDOUR::framecnt_t>, sigc::slot<bool, ARDOUR::framecnt_t>);
377         void set_state_from_config ();
378         void add_to_page (OptionEditorPage *);
379         void set_session (ARDOUR::Session *);
380
381 private:
382         Gtk::Label _label;
383         AudioClock _clock;
384         sigc::slot<ARDOUR::framecnt_t> _get;
385         sigc::slot<bool, ARDOUR::framecnt_t> _set;
386 };
387
388 class DirectoryOption : public Option
389 {
390 public:
391         DirectoryOption (std::string const &, std::string const &, sigc::slot<std::string>, sigc::slot<bool, std::string>);
392
393         void set_state_from_config ();
394         void add_to_page (OptionEditorPage *);
395
396 private:
397         void file_set ();
398         void current_folder_set ();
399         
400         sigc::slot<std::string> _get; ///< slot to get the configuration variable's value
401         sigc::slot<bool, std::string> _set;  ///< slot to set the configuration variable's value
402         Gtk::FileChooserButton _file_chooser;
403 };
404
405 /** Class to represent a single page in an OptionEditor's notebook.
406  *  Pages are laid out using a 3-column table; the 1st column is used
407  *  to indent non-headings, and the 2nd and 3rd for actual content.
408  */
409 class OptionEditorPage
410 {
411 public:
412         OptionEditorPage (Gtk::Notebook&, std::string const &);
413
414         Gtk::VBox box;
415         Gtk::Table table;
416         std::list<OptionEditorComponent*> components;
417 };
418
419 /** The OptionEditor dialog base class */
420 class OptionEditor : public ArdourWindow
421 {
422 public:
423         OptionEditor (ARDOUR::Configuration *, std::string const &);
424         ~OptionEditor ();
425
426         void add_option (std::string const &, OptionEditorComponent *);
427
428         void set_current_page (std::string const &);
429
430 protected:
431
432         virtual void parameter_changed (std::string const &);
433
434         ARDOUR::Configuration* _config;
435
436 private:
437
438         PBD::ScopedConnection config_connection;
439
440         Gtk::Notebook _notebook;
441         std::map<std::string, OptionEditorPage*> _pages;
442 };
443
444 #endif /* __gtk_ardour_option_editor_h__ */
445
446