Build fixes for Boost >= 1.73
[dcpomatic.git] / src / wx / content_widget.h
index 8b76160443fd0cf31fe34e75e710ec0faf5a3d64..52a5e5851a9b09ecaef7bcea415b1c7b66007be5 100644 (file)
@@ -1,19 +1,20 @@
 /*
-    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
 
-    This program is free software; you can redistribute it and/or modify
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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,
+    DCP-o-matic 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 
  *  @brief ContentWidget class.
  */
 
-#ifndef DCPOMATIC_MULTIPLE_WIDGET_H
-#define DCPOMATIC_MULTIPLE_WIDGET_H
+#ifndef DCPOMATIC_CONTENT_WIDGET_H
+#define DCPOMATIC_CONTENT_WIDGET_H
 
-#include <vector>
+#include "wx_util.h"
+#include "lib/content.h"
 #include <wx/wx.h>
 #include <wx/gbsizer.h>
+#include <wx/spinctrl.h>
 #include <boost/function.hpp>
-#include "wx_util.h"
+#include <vector>
 
 /** @class ContentWidget
  *  @brief A widget which represents some Content state and which can be used
  *  when multiple pieces of content are selected.
  *
- *  @param S Type containing the content being represented (e.g. VideoContent)
+ *  @param S Type of ContentPart being manipulated (e.g. VideoContent)
  *  @param T Type of the widget (e.g. wxSpinCtrl)
  *  @param U Data type of state as used by the model.
  *  @param V Data type of state as used by the view.
  */
 template <class S, class T, typename U, typename V>
-class ContentWidget
+class ContentWidget : public boost::noncopyable
 {
 public:
        /** @param parent Parent window.
         *  @param wrapped Control widget that we are wrapping.
         *  @param property ContentProperty that the widget is handling.
+        *  @param part Part of Content that the property is in (e.g. &Content::video)
         *  @param model_getter Function on the Content to get the value.
         *  @param model_setter Function on the Content to set the value.
+        *  @param view_changed Function called when the view has changed; useful for linking controls.
+        *  @param view_to_model Function to convert a view value to a model value.
+        *  @param model_to_view Function to convert a model value to a view value.
         */
        ContentWidget (
                wxWindow* parent,
                T* wrapped,
                int property,
+               boost::function<boost::shared_ptr<S> (Content*)> part,
                boost::function<U (S*)> model_getter,
                boost::function<void (S*, U)> model_setter,
+               boost::function<void ()> view_changed,
                boost::function<U (V)> view_to_model,
                boost::function<V (U)> model_to_view
                )
@@ -62,8 +71,10 @@ public:
                , _sizer (0)
                , _button (new wxButton (parent, wxID_ANY, _("Multiple values")))
                , _property (property)
+               , _part (part)
                , _model_getter (model_getter)
                , _model_setter (model_setter)
+               , _view_changed (view_changed)
                , _view_to_model (view_to_model)
                , _model_to_view (model_to_view)
                , _ignore_model_changes (false)
@@ -79,7 +90,7 @@ public:
                return _wrapped;
        }
 
-       typedef std::vector<boost::shared_ptr<S> > List;
+       typedef std::vector<boost::shared_ptr<Content> > List;
 
        /** Set the content that this control is working on (i.e. the selected content) */
        void set_content (List content)
@@ -89,7 +100,7 @@ public:
                }
 
                _connections.clear ();
-               
+
                _content = content;
 
                _wrapped->Enable (!_content.empty ());
@@ -97,16 +108,21 @@ public:
                update_from_model ();
 
                for (typename List::iterator i = _content.begin(); i != _content.end(); ++i) {
-                       _connections.push_back ((*i)->Changed.connect (boost::bind (&ContentWidget::model_changed, this, _2)));
+#if BOOST_VERSION >= 106100
+                       _connections.push_back ((*i)->Change.connect (boost::bind (&ContentWidget::model_changed, this, boost::placeholders::_1, boost::placeholders::_3)));
+#else
+                       _connections.push_back ((*i)->Change.connect (boost::bind (&ContentWidget::model_changed, this, _1, _3)));
+#endif
                }
        }
 
        /** Add this widget to a wxGridBagSizer */
-       void add (wxGridBagSizer* sizer, wxGBPosition position)
+       void add (wxGridBagSizer* sizer, wxGBPosition position, wxGBSpan span = wxDefaultSpan)
        {
                _sizer = sizer;
                _position = position;
-               _sizer->Add (_wrapped, _position);
+               _span = span;
+               _sizer->Add (_wrapped, _position, _span);
        }
 
        /** Update the view from the model */
@@ -118,8 +134,8 @@ public:
                }
 
                typename List::iterator i = _content.begin ();
-               U const v = boost::bind (_model_getter, _content.front().get())();
-               while (i != _content.end() && boost::bind (_model_getter, i->get())() == v) {
+               U const v = boost::bind (_model_getter, _part(_content.front().get()).get())();
+               while (i != _content.end() && boost::bind (_model_getter, _part(i->get()).get())() == v) {
                        ++i;
                }
 
@@ -135,62 +151,73 @@ public:
        {
                _ignore_model_changes = true;
                for (size_t i = 0; i < _content.size(); ++i) {
-                       boost::bind (_model_setter, _content[i].get(), _view_to_model (wx_get (_wrapped))) ();
+                       boost::bind (_model_setter, _part (_content[i].get()).get(), _view_to_model (wx_get (_wrapped))) ();
+               }
+               if (_view_changed) {
+                       _view_changed ();
                }
                _ignore_model_changes = false;
        }
-       
+
+       void show (bool s)
+       {
+               _wrapped->Show (s);
+       }
+
 private:
-       
+
        void set_single ()
        {
-               if (_wrapped->IsShown ()) {
+               if (_wrapped->IsShown() || !_sizer) {
                        return;
                }
 
                _sizer->Detach (_button);
                _button->Hide ();
-               _sizer->Add (_wrapped, _position);
+               _sizer->Add (_wrapped, _position, _span);
                _wrapped->Show ();
                _sizer->Layout ();
        }
 
        void set_multiple ()
        {
-               if (_button->IsShown ()) {
+               if (_button->IsShown() || !_sizer) {
                        return;
                }
-               
+
                _wrapped->Hide ();
                _sizer->Detach (_wrapped);
                _button->Show ();
-               _sizer->Add (_button, _position);
+               _sizer->Add (_button, _position, _span);
                _sizer->Layout ();
        }
 
        void button_clicked ()
        {
-               U const v = boost::bind (_model_getter, _content.front().get())();
+               U const v = boost::bind (_model_getter, _part(_content.front().get()).get())();
                for (typename List::iterator i = _content.begin (); i != _content.end(); ++i) {
-                       boost::bind (_model_setter, i->get(), v) ();
+                       boost::bind (_model_setter, _part(i->get()).get(), v) ();
                }
        }
 
-       void model_changed (int property)
+       void model_changed (ChangeType type, int property)
        {
-               if (property == _property && !_ignore_model_changes) {
+               if (type == CHANGE_TYPE_DONE && property == _property && !_ignore_model_changes) {
                        update_from_model ();
                }
        }
-       
+
        T* _wrapped;
        wxGridBagSizer* _sizer;
        wxGBPosition _position;
+       wxGBSpan _span;
        wxButton* _button;
        List _content;
        int _property;
+       boost::function<boost::shared_ptr<S> (Content *)> _part;
        boost::function<U (S*)> _model_getter;
        boost::function<void (S*, U)> _model_setter;
+       boost::function<void ()> _view_changed;
        boost::function<U (V)> _view_to_model;
        boost::function<V (U)> _model_to_view;
        std::list<boost::signals2::connection> _connections;
@@ -211,14 +238,18 @@ public:
                wxWindow* parent,
                wxSpinCtrl* wrapped,
                int property,
+               boost::function<boost::shared_ptr<S> (Content *)> part,
                boost::function<int (S*)> getter,
-               boost::function<void (S*, int)> setter
+               boost::function<void (S*, int)> setter,
+               boost::function<void ()> view_changed = boost::function<void ()>()
                )
                : ContentWidget<S, wxSpinCtrl, int, int> (
                        parent,
                        wrapped,
                        property,
+                       part,
                        getter, setter,
+                       view_changed,
                        &caster<int, int>,
                        &caster<int, int>
                        )
@@ -227,6 +258,34 @@ public:
        }
 };
 
+template <class S>
+class ContentSpinCtrlDouble : public ContentWidget<S, wxSpinCtrlDouble, double, double>
+{
+public:
+       ContentSpinCtrlDouble (
+               wxWindow* parent,
+               wxSpinCtrlDouble* wrapped,
+               int property,
+               boost::function<boost::shared_ptr<S> (Content *)> part,
+               boost::function<double (S*)> getter,
+               boost::function<void (S*, double)> setter,
+               boost::function<void ()> view_changed = boost::function<void ()>()
+               )
+               : ContentWidget<S, wxSpinCtrlDouble, double, double> (
+                       parent,
+                       wrapped,
+                       property,
+                       part,
+                       getter, setter,
+                       view_changed,
+                       &caster<double, double>,
+                       &caster<double, double>
+                       )
+       {
+               wrapped->Bind (wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, boost::bind (&ContentWidget<S, wxSpinCtrlDouble, double, double>::view_changed, this));
+       }
+};
+
 template <class S, class U>
 class ContentChoice : public ContentWidget<S, wxChoice, U, int>
 {
@@ -235,17 +294,21 @@ public:
                wxWindow* parent,
                wxChoice* wrapped,
                int property,
+               boost::function<boost::shared_ptr<S> (Content *)> part,
                boost::function<U (S*)> getter,
                boost::function<void (S*, U)> setter,
                boost::function<U (int)> view_to_model,
-               boost::function<int (U)> model_to_view
+               boost::function<int (U)> model_to_view,
+               boost::function<void ()> view_changed = boost::function<void()>()
                )
                : ContentWidget<S, wxChoice, U, int> (
                        parent,
                        wrapped,
                        property,
+                       part,
                        getter,
                        setter,
+                       view_changed,
                        view_to_model,
                        model_to_view
                        )