Basic multiple selection for cropping.
[dcpomatic.git] / src / wx / multiple_widget.h
1 /*
2     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
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 DCPOMATIC_MULTIPLE_WIDGET_H
21 #define DCPOMATIC_MULTIPLE_WIDGET_H
22
23 #include <vector>
24 #include <wx/wx.h>
25 #include <wx/gbsizer.h>
26 #include <boost/function.hpp>
27 #include "wx_util.h"
28
29 template <class T>
30 class MultipleWidget
31 {
32 public:
33         MultipleWidget (wxWindow* parent, T* wrapped)
34                 : _wrapped (wrapped)
35                 , _sizer (0)
36                 , _button (new wxButton (parent, wxID_ANY, _("Multiple values")))
37         {
38                 _button->SetToolTip (_("Click the button to set all selections to the same value"));
39                 _button->Hide ();
40                 _button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&MultipleWidget::button_clicked, this));
41         }
42
43         T* wrapped () const
44         {
45                 return _wrapped;
46         }
47
48         void add (wxGridBagSizer* sizer, wxGBPosition position)
49         {
50                 _sizer = sizer;
51                 _position = position;
52                 _sizer->Add (_wrapped, _position);
53         }
54
55         void set_single ()
56         {
57                 if (_wrapped->IsShown ()) {
58                         return;
59                 }
60
61                 _sizer->Detach (_button);
62                 _button->Hide ();
63                 _sizer->Add (_wrapped, _position);
64                 _wrapped->Show ();
65                 _sizer->Layout ();
66         }
67
68         void set_multiple ()
69         {
70                 if (_button->IsShown ()) {
71                         return;
72                 }
73                 
74                 _wrapped->Hide ();
75                 _sizer->Detach (_wrapped);
76                 _button->Show ();
77                 _sizer->Add (_button, _position);
78                 _sizer->Layout ();
79         }
80
81         boost::signals2::signal<void (void)> SetAllSame;
82
83 private:
84         void button_clicked ()
85         {
86                 SetAllSame ();
87         }
88         
89         T* _wrapped;
90         wxGridBagSizer* _sizer;
91         wxGBPosition _position;
92         wxButton* _button;
93 };
94
95
96 /** Set up some MultipleWidget<SpinCtrl> using a (possibly) multiple selection of objects of type T.
97  *  The value is obtained from the T objects using getter.
98  */
99 template <class T>
100 void
101 set_multiple (std::vector<boost::shared_ptr<T> > data, MultipleWidget<wxSpinCtrl>* widget, boost::function<int (T*)> getter)
102 {
103         if (data.empty ()) {
104                 widget->set_single ();
105                 widget->wrapped()->SetValue (0);
106                 return;
107         }
108         
109         typename std::vector<boost::shared_ptr<T> >::iterator i = data.begin();
110         int first = boost::bind (getter, data.front().get()) ();
111         while (i != data.end() && boost::bind (getter, i->get())() == first) {
112                 ++i;
113         }
114
115         if (i == data.end ()) {
116                 /* All values are the same */
117                 widget->set_single ();
118                 checked_set (widget->wrapped(), first);
119         } else {
120                 /* At least one different value */
121                 widget->set_multiple ();
122         }
123 }
124
125 #endif