From: Carl Hetherington Date: Mon, 11 Nov 2013 15:41:31 +0000 (+0000) Subject: Pull more stuff into ContentWidget. X-Git-Tag: v2.0.48~1163 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=1e1e5b454c72d818c9fe142296d489c7983a5849 Pull more stuff into ContentWidget. --- diff --git a/src/wx/content_widget.h b/src/wx/content_widget.h new file mode 100644 index 000000000..32fabda97 --- /dev/null +++ b/src/wx/content_widget.h @@ -0,0 +1,175 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program 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, + 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. + +*/ + +#ifndef DCPOMATIC_MULTIPLE_WIDGET_H +#define DCPOMATIC_MULTIPLE_WIDGET_H + +#include +#include +#include +#include +#include "wx_util.h" + +/** 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 T Type of the widget (e.g. wxSpinCtrl) + */ +template +class ContentWidget +{ +public: + /** @param parent Parent window. + * @param wrapped Control widget that we are wrapping. + * @param property ContentProperty that the widget is handling. + * @param getter Function on the Content to get the value. + * @param setter Function on the Content to set the value. + */ + ContentWidget (wxWindow* parent, T* wrapped, int property, boost::function getter, boost::function setter) + : _wrapped (wrapped) + , _sizer (0) + , _button (new wxButton (parent, wxID_ANY, _("Multiple values"))) + , _property (property) + , _getter (getter) + , _setter (setter) + , _ignore_model_changes (false) + { + _button->SetToolTip (_("Click the button to set all selected content to the same value.")); + _button->Hide (); + _button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ContentWidget::button_clicked, this)); + _wrapped->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&ContentWidget::view_changed, this)); + } + + T* wrapped () const { + return _wrapped; + } + + typedef std::vector > List; + + void set_content (List content) + { + for (typename std::list::iterator i = _connections.begin(); i != _connections.end(); ++i) { + i->disconnect (); + } + + _content = content; + + _wrapped->Enable (!_content.empty ()); + + 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))); + } + } + + void add (wxGridBagSizer* sizer, wxGBPosition position) + { + _sizer = sizer; + _position = position; + _sizer->Add (_wrapped, _position); + } + +private: + + void set_single () + { + if (_wrapped->IsShown ()) { + return; + } + + _sizer->Detach (_button); + _button->Hide (); + _sizer->Add (_wrapped, _position); + _wrapped->Show (); + _sizer->Layout (); + } + + void set_multiple () + { + if (_button->IsShown ()) { + return; + } + + _wrapped->Hide (); + _sizer->Detach (_wrapped); + _button->Show (); + _sizer->Add (_button, _position); + _sizer->Layout (); + } + + void button_clicked () + { + int const v = boost::bind (_getter, _content.front().get())(); + for (typename List::iterator i = _content.begin (); i != _content.end(); ++i) { + boost::bind (_setter, i->get(), v) (); + } + } + + void view_changed () + { + 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 (_setter, _content[i].get(), _wrapped->GetValue ()) (); + } + } + + void update_from_model () + { + if (_content.empty ()) { + set_single (); + return; + } + + typename List::iterator i = _content.begin (); + int const v = boost::bind (_getter, _content.front().get())(); + while (i != _content.end() && boost::bind (_getter, i->get())() == v) { + ++i; + } + + if (i == _content.end ()) { + set_single (); + checked_set (_wrapped, v); + } else { + set_multiple (); + } + } + + void model_changed (int property) + { + if (property == _property && !_ignore_model_changes) { + update_from_model (); + } + } + + T* _wrapped; + wxGridBagSizer* _sizer; + wxGBPosition _position; + wxButton* _button; + List _content; + int _property; + boost::function _getter; + boost::function _setter; + std::list _connections; + bool _ignore_model_changes; +}; + +#endif diff --git a/src/wx/multiple_widget.h b/src/wx/multiple_widget.h deleted file mode 100644 index 7c0b4a614..000000000 --- a/src/wx/multiple_widget.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright (C) 2013 Carl Hetherington - - This program 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, - 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. - -*/ - -#ifndef DCPOMATIC_MULTIPLE_WIDGET_H -#define DCPOMATIC_MULTIPLE_WIDGET_H - -#include -#include -#include -#include -#include "wx_util.h" - -template -class MultipleWidget -{ -public: - MultipleWidget (wxWindow* parent, T* wrapped) - : _wrapped (wrapped) - , _sizer (0) - , _button (new wxButton (parent, wxID_ANY, _("Multiple values"))) - { - _button->SetToolTip (_("Click the button to set all selections to the same value")); - _button->Hide (); - _button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&MultipleWidget::button_clicked, this)); - } - - T* wrapped () const - { - return _wrapped; - } - - void add (wxGridBagSizer* sizer, wxGBPosition position) - { - _sizer = sizer; - _position = position; - _sizer->Add (_wrapped, _position); - } - - void set_single () - { - if (_wrapped->IsShown ()) { - return; - } - - _sizer->Detach (_button); - _button->Hide (); - _sizer->Add (_wrapped, _position); - _wrapped->Show (); - _sizer->Layout (); - } - - void set_multiple () - { - if (_button->IsShown ()) { - return; - } - - _wrapped->Hide (); - _sizer->Detach (_wrapped); - _button->Show (); - _sizer->Add (_button, _position); - _sizer->Layout (); - } - - boost::signals2::signal SetAllSame; - -private: - void button_clicked () - { - SetAllSame (); - } - - T* _wrapped; - wxGridBagSizer* _sizer; - wxGBPosition _position; - wxButton* _button; -}; - - -/** Set up some MultipleWidget using a (possibly) multiple selection of objects of type T. - * The value is obtained from the T objects using getter. - */ -template -void -set_multiple (std::vector > data, MultipleWidget* widget, boost::function getter) -{ - if (data.empty ()) { - widget->set_single (); - widget->wrapped()->SetValue (0); - return; - } - - typename std::vector >::iterator i = data.begin(); - int first = boost::bind (getter, data.front().get()) (); - while (i != data.end() && boost::bind (getter, i->get())() == first) { - ++i; - } - - if (i == data.end ()) { - /* All values are the same */ - widget->set_single (); - checked_set (widget->wrapped(), first); - } else { - /* At least one different value */ - widget->set_multiple (); - } -} - -#endif diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc index 3b4dc7e46..ca1fd1ce8 100644 --- a/src/wx/video_panel.cc +++ b/src/wx/video_panel.cc @@ -29,7 +29,7 @@ #include "wx_util.h" #include "film_editor.h" #include "content_colour_conversion_dialog.h" -#include "multiple_widget.h" +#include "content_widget.h" using std::vector; using std::string; @@ -55,22 +55,46 @@ VideoPanel::VideoPanel (FilmEditor* e) ++r; add_label_to_grid_bag_sizer (grid, this, _("Left crop"), true, wxGBPosition (r, 0)); - _left_crop = new MultipleWidget (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _left_crop = new ContentWidget ( + this, + new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)), + VideoContentProperty::VIDEO_CROP, + boost::mem_fn (&VideoContent::left_crop), + boost::mem_fn (&VideoContent::set_left_crop) + ); _left_crop->add (grid, wxGBPosition (r, 1)); ++r; add_label_to_grid_bag_sizer (grid, this, _("Right crop"), true, wxGBPosition (r, 0)); - _right_crop = new MultipleWidget (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _right_crop = new ContentWidget ( + this, + new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)), + VideoContentProperty::VIDEO_CROP, + boost::mem_fn (&VideoContent::right_crop), + boost::mem_fn (&VideoContent::set_right_crop) + ); _right_crop->add (grid, wxGBPosition (r, 1)); ++r; add_label_to_grid_bag_sizer (grid, this, _("Top crop"), true, wxGBPosition (r, 0)); - _top_crop = new MultipleWidget (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _top_crop = new ContentWidget ( + this, + new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)), + VideoContentProperty::VIDEO_CROP, + boost::mem_fn (&VideoContent::top_crop), + boost::mem_fn (&VideoContent::set_top_crop) + ); _top_crop->add (grid, wxGBPosition (r,1 )); ++r; add_label_to_grid_bag_sizer (grid, this, _("Bottom crop"), true, wxGBPosition (r, 0)); - _bottom_crop = new MultipleWidget (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _bottom_crop = new ContentWidget ( + this, + new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)), + VideoContentProperty::VIDEO_CROP, + boost::mem_fn (&VideoContent::bottom_crop), + boost::mem_fn (&VideoContent::set_bottom_crop) + ); _bottom_crop->add (grid, wxGBPosition (r, 1)); ++r; @@ -136,57 +160,11 @@ VideoPanel::VideoPanel (FilmEditor* e) _frame_type->Append (_("3D left/right")); _frame_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&VideoPanel::frame_type_changed, this)); - _left_crop->SetAllSame.connect (boost::bind (&VideoPanel::set_left_crop_same, this)); - _left_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::left_crop_changed, this)); - _right_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::right_crop_changed, this)); - _top_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::top_crop_changed, this)); - _bottom_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::bottom_crop_changed, this)); _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)); } - -/** Called when the left crop widget has been changed */ -void -VideoPanel::left_crop_changed () -{ - VideoContentList c = _editor->selected_video_content (); - for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { - (*i)->set_left_crop (_left_crop->wrapped()->GetValue ()); - } -} - -/** Called when the right crop widget has been changed */ -void -VideoPanel::right_crop_changed () -{ - VideoContentList c = _editor->selected_video_content (); - for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { - (*i)->set_right_crop (_right_crop->wrapped()->GetValue ()); - } -} - -/** Called when the top crop widget has been changed */ -void -VideoPanel::top_crop_changed () -{ - VideoContentList c = _editor->selected_video_content (); - for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { - (*i)->set_top_crop (_top_crop->wrapped()->GetValue ()); - } -} - -/** Called when the bottom crop value has been changed */ -void -VideoPanel::bottom_crop_changed () -{ - VideoContentList c = _editor->selected_video_content (); - for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { - (*i)->set_bottom_crop (_bottom_crop->wrapped()->GetValue ()); - } -} - void VideoPanel::film_changed (Film::Property property) { @@ -215,10 +193,6 @@ VideoPanel::film_content_changed (int property) checked_set (_frame_type, vcs ? vcs->video_frame_type () : VIDEO_FRAME_TYPE_2D); setup_description (); } else if (property == VideoContentProperty::VIDEO_CROP) { - set_multiple (vc, _left_crop, &VideoContent::left_crop); - set_multiple (vc, _right_crop, &VideoContent::right_crop); - set_multiple (vc, _top_crop, &VideoContent::top_crop); - set_multiple (vc, _bottom_crop, &VideoContent::bottom_crop); setup_description (); } else if (property == VideoContentProperty::VIDEO_RATIO) { if (vcs) { @@ -404,13 +378,11 @@ VideoPanel::content_selection_changed () { VideoContentList sel = _editor->selected_video_content (); bool const single = sel.size() == 1; - bool const multiple = sel.size() > 1; - /* Things that are allowed with multiple selections */ - _left_crop->wrapped()->Enable (single || multiple); - _right_crop->wrapped()->Enable (single || multiple); - _top_crop->wrapped()->Enable (single || multiple); - _bottom_crop->wrapped()->Enable (single || multiple); + _left_crop->set_content (sel); + _right_crop->set_content (sel); + _top_crop->set_content (sel); + _bottom_crop->set_content (sel); /* Things that are only allowed with single selections */ _frame_type->Enable (single); @@ -425,13 +397,3 @@ VideoPanel::content_selection_changed () film_content_changed (VideoContentProperty::COLOUR_CONVERSION); film_content_changed (FFmpegContentProperty::FILTERS); } - -void -VideoPanel::set_left_crop_same () -{ - VideoContentList sel = _editor->selected_video_content (); - for (VideoContentList::iterator i = sel.begin(); i != sel.end(); ++i) { - (*i)->set_left_crop (sel.front()->left_crop ()); - } -} - diff --git a/src/wx/video_panel.h b/src/wx/video_panel.h index 5b0c95880..b4e0eb71b 100644 --- a/src/wx/video_panel.h +++ b/src/wx/video_panel.h @@ -19,7 +19,7 @@ #include "lib/film.h" #include "film_editor_panel.h" -#include "multiple_widget.h" +#include "content_widget.h" class wxChoice; class wxStaticText; @@ -36,11 +36,6 @@ public: void content_selection_changed (); private: - void set_left_crop_same (); - void left_crop_changed (); - void right_crop_changed (); - void top_crop_changed (); - void bottom_crop_changed (); void edit_filters_clicked (); void ratio_changed (); void frame_type_changed (); @@ -49,10 +44,10 @@ private: void setup_description (); wxChoice* _frame_type; - MultipleWidget* _left_crop; - MultipleWidget* _right_crop; - MultipleWidget* _top_crop; - MultipleWidget* _bottom_crop; + ContentWidget* _left_crop; + ContentWidget* _right_crop; + ContentWidget* _top_crop; + ContentWidget* _bottom_crop; wxChoice* _ratio; wxStaticText* _ratio_description; wxStaticText* _description;