int property,
boost::function<U (S*)> model_getter,
boost::function<void (S*, U)> model_setter,
- boost::function<V (T*)> view_getter
+ boost::function<U (V)> view_to_model,
+ boost::function<V (U)> model_to_view
)
: _wrapped (wrapped)
, _sizer (0)
, _property (property)
, _model_getter (model_getter)
, _model_setter (model_setter)
- , _view_getter (view_getter)
+ , _view_to_model (view_to_model)
+ , _model_to_view (model_to_view)
, _ignore_model_changes (false)
{
_button->SetToolTip (_("Click the button to set all selected content to the same value."));
_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ContentWidget::button_clicked, this));
}
- T* wrapped () const {
+ /** @return the widget that we are wrapping */
+ T* wrapped () const
+ {
return _wrapped;
}
typedef std::vector<boost::shared_ptr<S> > List;
+ /** Set the content that this control is working on (i.e. the selected content) */
void set_content (List content)
{
for (typename std::list<boost::signals2::connection>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
}
}
+ /** Add this widget to a wxGridBagSizer */
void add (wxGridBagSizer* sizer, wxGBPosition position)
{
_sizer = sizer;
_sizer->Add (_wrapped, _position);
}
+ /** Update the view from the model */
void update_from_model ()
{
if (_content.empty ()) {
if (i == _content.end ()) {
set_single ();
- checked_set (_wrapped, v);
+ checked_set (_wrapped, _model_to_view (v));
} else {
set_multiple ();
}
void view_changed ()
{
+ _ignore_model_changes = true;
for (size_t i = 0; i < _content.size(); ++i) {
- /* Only update our view on the last time round this loop */
- _ignore_model_changes = i < (_content.size() - 1);
- boost::bind (_model_setter, _content[i].get(), static_cast<U> (boost::bind (_view_getter, _wrapped)()))();
+ boost::bind (_model_setter, _content[i].get(), _view_to_model (wx_get (_wrapped))) ();
}
+ _ignore_model_changes = false;
}
private:
int _property;
boost::function<U (S*)> _model_getter;
boost::function<void (S*, U)> _model_setter;
- boost::function<V (T*)> _view_getter;
+ boost::function<U (V)> _view_to_model;
+ boost::function<V (U)> _model_to_view;
std::list<boost::signals2::connection> _connections;
bool _ignore_model_changes;
};
+template <typename U, typename V>
+V caster (U x)
+{
+ return static_cast<V> (x);
+}
+
template <class S>
class ContentSpinCtrl : public ContentWidget<S, wxSpinCtrl, int, int>
{
public:
- ContentSpinCtrl (wxWindow* parent, wxSpinCtrl* wrapped, int property, boost::function<int (S*)> getter, boost::function<void (S*, int)> setter)
- : ContentWidget<S, wxSpinCtrl, int, int> (parent, wrapped, property, getter, setter, boost::mem_fn (&wxSpinCtrl::GetValue))
+ ContentSpinCtrl (
+ wxWindow* parent,
+ wxSpinCtrl* wrapped,
+ int property,
+ boost::function<int (S*)> getter,
+ boost::function<void (S*, int)> setter
+ )
+ : ContentWidget<S, wxSpinCtrl, int, int> (
+ parent,
+ wrapped,
+ property,
+ getter, setter,
+ &caster<int, int>,
+ &caster<int, int>
+ )
{
wrapped->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&ContentWidget<S, wxSpinCtrl, int, int>::view_changed, this));
}
-
};
template <class S, class U>
class ContentChoice : public ContentWidget<S, wxChoice, U, int>
{
public:
- ContentChoice (wxWindow* parent, wxChoice* wrapped, int property, boost::function<U (S*)> getter, boost::function<void (S*, U)> setter)
- : ContentWidget<S, wxChoice, U, int> (parent, wrapped, property, getter, setter, boost::mem_fn (&wxChoice::GetSelection))
+ ContentChoice (
+ wxWindow* parent,
+ wxChoice* wrapped,
+ int property,
+ 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
+ )
+ : ContentWidget<S, wxChoice, U, int> (
+ parent,
+ wrapped,
+ property,
+ getter,
+ setter,
+ view_to_model,
+ model_to_view
+ )
{
wrapped->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&ContentWidget<S, wxChoice, U, int>::view_changed, this));
}
using boost::bind;
using boost::optional;
+static Ratio const *
+index_to_ratio (int n)
+{
+ assert (n >= 0);
+
+ vector<Ratio const *> ratios = Ratio::all ();
+ if (n >= int (ratios.size ())) {
+ return 0;
+ }
+
+ return ratios[n];
+}
+
+static int
+ratio_to_index (Ratio const * r)
+{
+ vector<Ratio const *> ratios = Ratio::all ();
+ size_t i = 0;
+ while (i < ratios.size() && ratios[i] != r) {
+ ++i;
+ }
+
+ return i;
+}
+
VideoPanel::VideoPanel (FilmEditor* e)
: FilmEditorPanel (e, _("Video"))
{
new wxChoice (this, wxID_ANY),
VideoContentProperty::VIDEO_FRAME_TYPE,
boost::mem_fn (&VideoContent::video_frame_type),
- boost::mem_fn (&VideoContent::set_video_frame_type)
+ boost::mem_fn (&VideoContent::set_video_frame_type),
+ &caster<int, VideoFrameType>,
+ &caster<VideoFrameType, int>
);
_frame_type->add (grid, wxGBPosition (r, 1));
++r;
++r;
add_label_to_grid_bag_sizer (grid, this, _("Scale to"), true, wxGBPosition (r, 0));
- _ratio = new wxChoice (this, wxID_ANY);
- grid->Add (_ratio, wxGBPosition (r, 1));
+ _ratio = new ContentChoice<VideoContent, Ratio const *> (
+ this,
+ new wxChoice (this, wxID_ANY),
+ VideoContentProperty::VIDEO_RATIO,
+ boost::mem_fn (&VideoContent::ratio),
+ boost::mem_fn (&VideoContent::set_ratio),
+ &index_to_ratio,
+ &ratio_to_index
+ );
+ _ratio->add (grid, wxGBPosition (r, 1));
++r;
{
_bottom_crop->wrapped()->SetRange (0, 1024);
vector<Ratio const *> ratios = Ratio::all ();
- _ratio->Clear ();
+ _ratio->wrapped()->Clear ();
for (vector<Ratio const *>::iterator i = ratios.begin(); i != ratios.end(); ++i) {
- _ratio->Append (std_to_wx ((*i)->nickname ()));
+ _ratio->wrapped()->Append (std_to_wx ((*i)->nickname ()));
}
- _ratio->Append (_("No stretch"));
+ _ratio->wrapped()->Append (_("No stretch"));
_frame_type->wrapped()->Append (_("2D"));
_frame_type->wrapped()->Append (_("3D left/right"));
- _ratio->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&VideoPanel::ratio_changed, this));
_filters_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&VideoPanel::edit_filters_clicked, this));
_colour_conversion_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&VideoPanel::edit_colour_conversion_clicked, this));
}
} else if (property == VideoContentProperty::VIDEO_CROP) {
setup_description ();
} else if (property == VideoContentProperty::VIDEO_RATIO) {
- if (vcs) {
- int n = 0;
- vector<Ratio const *> ratios = Ratio::all ();
- vector<Ratio const *>::iterator i = ratios.begin ();
- while (i != ratios.end() && *i != vcs->ratio()) {
- ++i;
- ++n;
- }
-
- if (i == ratios.end()) {
- checked_set (_ratio, ratios.size ());
- } else {
- checked_set (_ratio, n);
- }
- } else {
- checked_set (_ratio, -1);
- }
setup_description ();
} else if (property == VideoContentProperty::VIDEO_FRAME_RATE) {
setup_description ();
_sizer->Layout ();
}
-
-void
-VideoPanel::ratio_changed ()
-{
- if (!_editor->film ()) {
- return;
- }
-
- VideoContentList vc = _editor->selected_video_content ();
- if (vc.size() != 1) {
- return;
- }
-
- int const n = _ratio->GetSelection ();
- if (n >= 0) {
- vector<Ratio const *> ratios = Ratio::all ();
- if (n < int (ratios.size ())) {
- vc.front()->set_ratio (ratios[n]);
- } else {
- vc.front()->set_ratio (0);
- }
- }
-}
-
void
VideoPanel::edit_colour_conversion_clicked ()
{
_top_crop->set_content (sel);
_bottom_crop->set_content (sel);
_frame_type->set_content (sel);
+ _ratio->set_content (sel);
/* Things that are only allowed with single selections */
- _ratio->Enable (single);
_filters_button->Enable (single);
_colour_conversion_button->Enable (single);
film_content_changed (VideoContentProperty::VIDEO_CROP);
- film_content_changed (VideoContentProperty::VIDEO_RATIO);
film_content_changed (VideoContentProperty::VIDEO_FRAME_RATE);
film_content_changed (VideoContentProperty::COLOUR_CONVERSION);
film_content_changed (FFmpegContentProperty::FILTERS);
private:
void edit_filters_clicked ();
- void ratio_changed ();
void edit_colour_conversion_clicked ();
void setup_description ();
ContentSpinCtrl<VideoContent>* _right_crop;
ContentSpinCtrl<VideoContent>* _top_crop;
ContentSpinCtrl<VideoContent>* _bottom_crop;
- wxChoice* _ratio;
+ ContentChoice<VideoContent, Ratio const *>* _ratio;
wxStaticText* _ratio_description;
wxStaticText* _description;
wxStaticText* _filters;
dcpomatic_setup_gettext_i18n (wx_to_std (locale->GetCanonicalName ()));
}
}
+
+int
+wx_get (wxSpinCtrl* w)
+{
+ return w->GetValue ();
+}
+
+int
+wx_get (wxChoice* w)
+{
+ return w->GetSelection ();
+}
extern void checked_set (wxRadioButton* widget, bool value);
extern void checked_set (wxStaticText* widget, std::string value);
+extern int wx_get (wxChoice* widget);
+extern int wx_get (wxSpinCtrl* widget);
+
/* GTK 2.24.17 has a buggy GtkFileChooserButton and it was put in Ubuntu 13.04.
This also seems to apply to 2.24.20 in Ubuntu 13.10
Use our own dir picker as this is the least bad option I can think of.