Fix CheckOption crash on session-reload
[ardour.git] / gtk2_ardour / option_editor.h
index e32c489f27694fe20d5de440ee2da8df5243344d..749df8f90c70e5631770da0e315b19fa44c71ca2 100644 (file)
     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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
 */
 
 #ifndef __gtk_ardour_option_editor_h__
 #define __gtk_ardour_option_editor_h__
 
-#include <gtkmm/notebook.h>
 #include <gtkmm/checkbutton.h>
 #include <gtkmm/comboboxtext.h>
+#include <gtkmm/filechooserbutton.h>
+#include <gtkmm/label.h>
+#include <gtkmm/notebook.h>
+#include <gtkmm/scale.h>
 #include <gtkmm/spinbutton.h>
 #include <gtkmm/table.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/treeview.h>
 #include <gtkmm/window.h>
 
-#include "gtkmm2ext/slider_controller.h"
+#include "widgets/slider_controller.h"
 
+#include "actions.h"
 #include "ardour_window.h"
 #include "audio_clock.h"
 #include "ardour/types.h"
@@ -73,11 +78,11 @@ public:
        virtual void add_to_page (OptionEditorPage *) = 0;
 
        void add_widget_to_page (OptionEditorPage*, Gtk::Widget*);
-       void add_widgets_to_page (OptionEditorPage*, Gtk::Widget*, Gtk::Widget*);
+       void add_widgets_to_page (OptionEditorPage*, Gtk::Widget*, Gtk::Widget*, bool expand = true);
 
        void set_note (std::string const &);
 
-        virtual Gtk::Widget& tip_widget() = 0;
+       virtual Gtk::Widget& tip_widget() = 0;
 
 protected:
        void maybe_add_note (OptionEditorPage *, int);
@@ -95,33 +100,26 @@ public:
        void set_state_from_config () {}
        void add_to_page (OptionEditorPage *);
 
-        Gtk::Widget& tip_widget() { return *_label; }
+       Gtk::Widget& tip_widget() { return *_label; }
 
 private:
        Gtk::Label* _label; ///< the label used for the heading
 };
 
-/** A component which provides a box into which a subclass can put arbitrary widgets */
-class OptionEditorBox : public OptionEditorComponent
+/** Expanding layout helper to push elements to the left on a single column page  */
+class OptionEditorBlank : public OptionEditorComponent
 {
 public:
+       OptionEditorBlank () {}
 
-       /** Construct an OpenEditorBox */
-       OptionEditorBox ()
-       {
-               _box = Gtk::manage (new Gtk::VBox);
-               _box->set_spacing (4);
-       }
-
-       void parameter_changed (std::string const &) = 0;
-       void set_state_from_config () = 0;
+       void parameter_changed (std::string const &) {}
+       void set_state_from_config () {}
        void add_to_page (OptionEditorPage *);
 
-        Gtk::Widget& tip_widget() { return *_box->children().front().get_widget(); }
-
-protected:
+       Gtk::Widget& tip_widget() { return _dummy; }
 
-       Gtk::VBox* _box; ///< constituent box for subclasses to add widgets to
+private:
+       Gtk::EventBox _dummy;
 };
 
 class RcConfigDisplay : public OptionEditorComponent
@@ -186,16 +184,44 @@ public:
        }
 
 protected:
-
        std::string _id;
        std::string _name;
 };
 
+/** Just a Gtk Checkbutton, masquerading as an option component */
+class CheckOption : public OptionEditorComponent , public Gtkmm2ext::Activatable
+{
+public:
+       CheckOption (std::string const &, std::string const &, Glib::RefPtr<Gtk::Action> act );
+       virtual ~CheckOption ();
+       void set_state_from_config () {}
+       void parameter_changed (std::string const &) {}
+       void add_to_page (OptionEditorPage*);
+
+       void set_sensitive (bool yn) {
+               _button->set_sensitive (yn);
+       }
+
+       Gtk::Widget& tip_widget() { return *_button; }
+
+protected:
+       void action_toggled ();
+       void action_sensitivity_changed () {}
+       void action_visibility_changed () {}
+
+       virtual void toggled ();
+
+       Gtk::CheckButton*      _button; ///< UI button
+       Gtk::Label*            _label; ///< label for button, so we can use markup
+
+private:
+       sigc::connection       _callback_connection;
+};
+
 /** Component which provides the UI to handle a boolean option using a GTK CheckButton */
 class BoolOption : public Option
 {
 public:
-
        BoolOption (std::string const &, std::string const &, sigc::slot<bool>, sigc::slot<bool, bool>);
        void set_state_from_config ();
        void add_to_page (OptionEditorPage*);
@@ -207,7 +233,6 @@ public:
        Gtk::Widget& tip_widget() { return *_button; }
 
 protected:
-
        virtual void toggled ();
 
        sigc::slot<bool>       _get; ///< slot to get the configuration variable's value
@@ -220,6 +245,7 @@ class RouteDisplayBoolOption : public BoolOption
 {
 public:
        RouteDisplayBoolOption (std::string const &, std::string const &, sigc::slot<bool>, sigc::slot<bool, bool>);
+
 protected:
        virtual void toggled ();
 };
@@ -245,7 +271,6 @@ private:
 class EntryOption : public Option
 {
 public:
-
        EntryOption (std::string const &, std::string const &, sigc::slot<std::string>, sigc::slot<bool, std::string>);
        void set_state_from_config ();
        void add_to_page (OptionEditorPage*);
@@ -255,7 +280,6 @@ public:
        Gtk::Widget& tip_widget() { return *_entry; }
 
 private:
-
        void activated ();
        bool focus_out (GdkEventFocus*);
        void filter_text (const Glib::ustring&, int*);
@@ -275,7 +299,6 @@ template <class T>
 class ComboOption : public Option
 {
 public:
-
        /** Construct an ComboOption.
         *  @param i id
         *  @param n User-visible name.
@@ -288,9 +311,9 @@ public:
                sigc::slot<T> g,
                sigc::slot<bool, T> s
                )
-               : Option (i, n),
-                 _get (g),
-                 _set (s)
+               : Option (i, n)
+               , _get (g)
+               , _set (s)
        {
                _label = Gtk::manage (new Gtk::Label (n + ":"));
                _label->set_alignment (0, 0.5);
@@ -298,7 +321,8 @@ public:
                _combo->signal_changed().connect (sigc::mem_fun (*this, &ComboOption::changed));
        }
 
-       void set_state_from_config () {
+       void set_state_from_config ()
+       {
                uint32_t r = 0;
                while (r < _options.size() && _get () != _options[r]) {
                        ++r;
@@ -318,31 +342,33 @@ public:
         *  @param e Enumeration.
         *  @param o User-visible name for this value.
         */
-       void add (T e, std::string const & o) {
+       void add (T e, std::string const & o)
+       {
                _options.push_back (e);
                _combo->append_text (o);
        }
 
-       void clear () {
+       void clear ()
+       {
                _combo->clear_items();
                _options.clear ();
        }
 
-       void changed () {
+       void changed ()
+       {
                uint32_t const r = _combo->get_active_row_number ();
                if (r < _options.size()) {
                        _set (_options[r]);
                }
        }
-
-       void set_sensitive (bool yn) {
+       void set_sensitive (bool yn)
+       {
                _combo->set_sensitive (yn);
        }
 
-        Gtk::Widget& tip_widget() { return *_combo; }
+       Gtk::Widget& tip_widget() { return *_combo; }
 
 private:
-
        sigc::slot<T> _get;
        sigc::slot<bool, T> _set;
        Gtk::Label* _label;
@@ -356,79 +382,43 @@ private:
 class HSliderOption : public Option
 {
 public:
-
-       /** Construct an ComboOption.
-        *  @param i id
-        *  @param n User-visible name.
-        *  @param g Slot to get the variable's value.
-        *  @param s Slot to set the variable's value.
-        */
        HSliderOption (
-               std::string const & i,
-               std::string const & n,
-               Gtk::Adjustment &adj
-               )
-               : Option (i, n)
-       {
-               _label = Gtk::manage (new Gtk::Label (n + ":"));
-               _label->set_alignment (0, 0.5);
-               _hscale = Gtk::manage (new Gtk::HScale(adj));
-               _adj = NULL;
-       }
-
-       HSliderOption (
-               std::string const & i,
-               std::string const & n,
-               Gtk::Adjustment *adj,
-               sigc::slot<float> g,
-               sigc::slot<bool, float> s
-               )
-               : Option (i, n)
-               , _get (g)
-               , _set (s)
-               , _adj (adj)
-       {
-               _label = Gtk::manage (new Gtk::Label (n + ":"));
-               _label->set_alignment (0, 0.5);
-               _hscale = Gtk::manage (new Gtk::HScale(*_adj));
-               _adj->signal_value_changed().connect (sigc::mem_fun (*this, &HSliderOption::changed));
-       }
-
-       void set_state_from_config () {
-               if (_adj) _adj->set_value (_get());
-       }
-
-       void changed () {
-               if (_adj) _set (_adj->get_value ());
-       }
-
-       void add_to_page (OptionEditorPage* p)
-       {
-               add_widgets_to_page (p, _label, _hscale);
-       }
+                       std::string const& i,
+                       std::string const& n,
+                       sigc::slot<float> g,
+                       sigc::slot<bool, float> s,
+                       double lower, double upper,
+                       double step_increment = 1,
+                       double page_increment = 10,
+                       double mult = 1.0,
+                       bool logarithmic = false
+               );
 
-       void set_sensitive (bool yn) {
-               _hscale->set_sensitive (yn);
-       }
+       void set_state_from_config ();
+       virtual void changed ();
+       void add_to_page (OptionEditorPage* p);
+       void set_sensitive (bool yn);
 
-       Gtk::Widget& tip_widget() { return *_hscale; }
-       Gtk::HScale& scale() { return *_hscale; }
+       Gtk::Widget& tip_widget() { return _hscale; }
+       Gtk::HScale& scale() { return _hscale; }
 
-private:
+protected:
        sigc::slot<float> _get;
        sigc::slot<bool, float> _set;
-       Gtk::Label* _label;
-       Gtk::HScale* _hscale;
-       Gtk::Adjustment* _adj;
+       Gtk::Adjustment _adj;
+       Gtk::HScale _hscale;
+       Gtk::Label _label;
+       double _mult;
+       bool _log;
 };
 
+
 /** Component which provides the UI to handle an enumerated option using a GTK ComboBox.
  *  The template parameter is the enumeration.
  */
 class ComboStringOption : public Option
 {
 public:
-
        /** Construct an ComboOption.
         *  @param i id
         *  @param n User-visible name.
@@ -440,53 +430,25 @@ public:
                std::string const & n,
                sigc::slot<std::string> g,
                sigc::slot<bool, std::string> s
-               )
-               : Option (i, n),
-                 _get (g),
-                 _set (s)
-       {
-               _label = Gtk::manage (new Gtk::Label (n + ":"));
-               _label->set_alignment (0, 0.5);
-               _combo = Gtk::manage (new Gtk::ComboBoxText);
-               _combo->signal_changed().connect (sigc::mem_fun (*this, &ComboStringOption::changed));
-       }
-
-       void set_state_from_config () {
-               _combo->set_active_text (_get());
-       }
+               );
 
-       void add_to_page (OptionEditorPage* p)
-       {
-               add_widgets_to_page (p, _label, _combo);
-       }
+       void set_state_from_config ();
+       void add_to_page (OptionEditorPage* p);
 
        /** Set the allowed strings for this option
         *  @param strings a vector of allowed strings
         */
-        void set_popdown_strings (const std::vector<std::string>& strings) {
-               _combo->clear_items ();
-               for (std::vector<std::string>::const_iterator i = strings.begin(); i != strings.end(); ++i) {
-                       _combo->append_text (*i);
-               }
-       }
-
-       void clear () {
-               _combo->clear_items();
-       }
+       void set_popdown_strings (const std::vector<std::string>& strings);
 
-       void changed () {
-               _set (_combo->get_active_text ());
-       }
-
-       void set_sensitive (bool yn) {
-               _combo->set_sensitive (yn);
-       }
+       void clear ();
+       void changed ();
+       void set_sensitive (bool yn);
 
-        Gtk::Widget& tip_widget() { return *_combo; }
+       Gtk::Widget& tip_widget() { return *_combo; }
 
 private:
-        sigc::slot<std::string> _get;
-        sigc::slot<bool, std::string> _set;
+       sigc::slot<std::string> _get;
+       sigc::slot<bool, std::string> _set;
        Gtk::Label* _label;
        Gtk::ComboBoxText* _combo;
 };
@@ -498,7 +460,6 @@ private:
 class BoolComboOption : public Option
 {
 public:
-
        BoolComboOption (
                std::string const &,
                std::string const &,
@@ -513,10 +474,9 @@ public:
        void changed ();
        void set_sensitive (bool);
 
-        Gtk::Widget& tip_widget() { return *_combo; }
+       Gtk::Widget& tip_widget() { return *_combo; }
 
 private:
-
        sigc::slot<bool> _get;
        sigc::slot<bool, bool> _set;
        Gtk::Label* _label;
@@ -524,7 +484,6 @@ private:
 };
 
 
-
 /** Component which provides the UI to handle an numeric option using a GTK SpinButton */
 template <class T>
 class SpinOption : public Option
@@ -556,10 +515,10 @@ public:
                float scale = 1,
                unsigned digits = 0
                )
-               : Option (i, n),
-                 _get (g),
-                 _set (s),
-                 _scale (scale)
+               : Option (i, n)
+               , _get (g)
+               , _set (s)
+               , _scale (scale)
        {
                _label = Gtk::manage (new Gtk::Label (n + ":"));
                _label->set_alignment (0, 0.5);
@@ -586,7 +545,7 @@ public:
 
        void add_to_page (OptionEditorPage* p)
        {
-               add_widgets_to_page (p, _label, _box);
+               add_widgets_to_page (p, _label, _box, false);
        }
 
        void changed ()
@@ -594,7 +553,7 @@ public:
                _set (static_cast<T> (_spin->get_value ()) * _scale);
        }
 
-        Gtk::Widget& tip_widget() { return *_spin; }
+       Gtk::Widget& tip_widget() { return *_spin; }
 
 private:
        sigc::slot<T> _get;
@@ -613,7 +572,7 @@ public:
        void set_state_from_config ();
        void add_to_page (OptionEditorPage *);
 
-        Gtk::Widget& tip_widget() { return *_db_slider; }
+       Gtk::Widget& tip_widget() { return *_db_slider; }
 
 private:
        void db_changed ();
@@ -621,7 +580,7 @@ private:
        bool on_key_press (GdkEventKey* ev);
 
        Gtk::Adjustment _db_adjustment;
-       Gtkmm2ext::HSliderController* _db_slider;
+       ArdourWidgets::HSliderController* _db_slider;
        Gtk::Entry _db_display;
        Gtk::Label _label;
        Gtk::HBox _box;
@@ -630,6 +589,21 @@ private:
        sigc::slot<bool, ARDOUR::gain_t> _set;
 };
 
+class WidgetOption : public Option
+{
+  public:
+       WidgetOption (std::string const & i, std::string const & n, Gtk::Widget& w);
+
+       void add_to_page (OptionEditorPage*);
+       void parameter_changed (std::string const &) {}
+       void set_state_from_config () {}
+
+       Gtk::Widget& tip_widget() { return *_widget; }
+
+  private:
+       Gtk::Widget* _widget;
+};
+
 class ClockOption : public Option
 {
 public:
@@ -638,8 +612,8 @@ public:
        void add_to_page (OptionEditorPage *);
        void set_session (ARDOUR::Session *);
 
-        Gtk::Widget& tip_widget() { return _clock; }
-        AudioClock& clock() { return _clock; }
+       Gtk::Widget& tip_widget() { return _clock; }
+       AudioClock& clock() { return _clock; }
 
 private:
        void save_clock_time ();
@@ -658,7 +632,7 @@ public:
        void set_state_from_config ();
        void add_to_page (OptionEditorPage *);
 
-        Gtk::Widget& tip_widget() { return _file_chooser; }
+       Gtk::Widget& tip_widget() { return _file_chooser; }
 
 private:
        void selection_changed ();
@@ -676,10 +650,30 @@ class OptionEditorPage
 {
 public:
        OptionEditorPage (Gtk::Notebook&, std::string const &);
+       OptionEditorPage ();
 
        Gtk::VBox box;
        Gtk::Table table;
        std::list<OptionEditorComponent*> components;
+
+private:
+       void init ();
+};
+
+class OptionEditorMiniPage : public OptionEditorComponent, public OptionEditorPage
+{
+public:
+       OptionEditorMiniPage ()
+       {
+               box.pack_start (table, false, false);
+               box.set_border_width (0);
+       }
+
+       void parameter_changed (std::string const &) = 0;
+       void set_state_from_config () = 0;
+       virtual void add_to_page (OptionEditorPage*);
+
+       Gtk::Widget& tip_widget() { return *table.children().front().get_widget(); }
 };
 
 /** The OptionEditor dialog base class */
@@ -703,14 +697,14 @@ protected:
 
        class OptionColumns : public Gtk::TreeModel::ColumnRecord
        {
-          public:
-               Gtk::TreeModelColumn<std::string> name;
-               Gtk::TreeModelColumn<Gtk::Widget*> widget;
-
-               OptionColumns() {
-                       add (name);
-                       add (widget);
-               }
+               public:
+                       Gtk::TreeModelColumn<std::string> name;
+                       Gtk::TreeModelColumn<Gtk::Widget*> widget;
+
+                       OptionColumns() {
+                               add (name);
+                               add (widget);
+                       }
        };
 
        OptionColumns option_columns;