/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
-#include "text_panel.h"
-#include "film_editor.h"
-#include "wx_util.h"
-#include "text_view.h"
+
+#include "check_box.h"
#include "content_panel.h"
-#include "fonts_dialog.h"
#include "dcp_text_track_dialog.h"
-#include "subtitle_appearance_dialog.h"
-#include "static_text.h"
-#include "check_box.h"
#include "dcpomatic_button.h"
+#include "dcpomatic_spin_ctrl.h"
+#include "film_editor.h"
#include "film_viewer.h"
-#include "lib/job_manager.h"
-#include "lib/ffmpeg_content.h"
-#include "lib/string_text_file_content.h"
-#include "lib/ffmpeg_subtitle_stream.h"
+#include "fonts_dialog.h"
+#include "language_tag_widget.h"
+#include "static_text.h"
+#include "subtitle_appearance_dialog.h"
+#include "text_panel.h"
+#include "text_view.h"
+#include "wx_util.h"
+#include "lib/analyse_subtitles_job.h"
+#include "lib/dcp_content.h"
#include "lib/dcp_subtitle_content.h"
-#include "lib/string_text_file_decoder.h"
#include "lib/dcp_subtitle_decoder.h"
-#include "lib/dcp_content.h"
-#include "lib/text_content.h"
#include "lib/decoder_factory.h"
-#include "lib/analyse_subtitles_job.h"
+#include "lib/ffmpeg_content.h"
+#include "lib/ffmpeg_subtitle_stream.h"
+#include "lib/job_manager.h"
+#include "lib/string_text_file_content.h"
+#include "lib/string_text_file_decoder.h"
#include "lib/subtitle_analysis.h"
+#include "lib/text_content.h"
+#include <dcp/warnings.h>
+LIBDCP_DISABLE_WARNINGS
#include <wx/spinctrl.h>
+LIBDCP_ENABLE_WARNINGS
+
-using std::vector;
-using std::string;
-using std::list;
using std::cout;
-using std::shared_ptr;
-using boost::optional;
using std::dynamic_pointer_cast;
+using std::list;
+using std::shared_ptr;
+using std::string;
+using std::vector;
using boost::bind;
+using boost::optional;
+
/** @param t Original text type of the content, if known */
TextPanel::TextPanel (ContentPanel* p, TextType t)
: ContentSubPanel (p, std_to_wx(text_type_to_name(t)))
- , _outline_subtitles (0)
- , _dcp_track_label (0)
- , _dcp_track (0)
- , _text_view (0)
- , _fonts_dialog (0)
, _original_type (t)
- , _loading_analysis (false)
+{
+
+}
+
+
+void
+TextPanel::create ()
{
wxString refer = _("Use this DCP's subtitle as OV and make VF");
- if (t == TextType::CLOSED_CAPTION) {
+ if (_original_type == TextType::CLOSED_CAPTION) {
refer = _("Use this DCP's closed caption as OV and make VF");
}
_burn = new CheckBox (this, _("Burn subtitles into image"));
-#ifdef __WXGTK3__
- int const spin_width = 118;
-#else
- int const spin_width = 56;
-#endif
-
_offset_label = create_label (this, _("Offset"), true);
_x_offset_label = create_label (this, _("X"), true);
- _x_offset = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(spin_width, -1));
+ _x_offset = new SpinCtrl (this, DCPOMATIC_SPIN_CTRL_WIDTH);
_x_offset_pc_label = new StaticText (this, _("%"));
_y_offset_label = create_label (this, _("Y"), true);
- _y_offset = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(spin_width, -1));
+ _y_offset = new SpinCtrl (this, DCPOMATIC_SPIN_CTRL_WIDTH);
_y_offset_pc_label = new StaticText (this, _("%"));
_scale_label = create_label (this, _("Scale"), true);
_x_scale_label = create_label (this, _("X"), true);
- _x_scale = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(spin_width, -1));
+ _x_scale = new SpinCtrl (this, DCPOMATIC_SPIN_CTRL_WIDTH);
_x_scale_pc_label = new StaticText (this, _("%"));
_y_scale_label = create_label (this, S_("Coord|Y"), true);
- _y_scale = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(spin_width, -1));
+ _y_scale = new SpinCtrl (this, DCPOMATIC_SPIN_CTRL_WIDTH);
_y_scale_pc_label = new StaticText (this, _("%"));
_line_spacing_label = create_label (this, _("Line spacing"), true);
- _line_spacing = new wxSpinCtrl (this);
+ _line_spacing = new SpinCtrl (this, DCPOMATIC_SPIN_CTRL_WIDTH);
_line_spacing_pc_label = new StaticText (this, _("%"));
_stream_label = create_label (this, _("Stream"), true);
_x_offset->SetRange (-100, 100);
_y_offset->SetRange (-100, 100);
- _x_scale->SetRange (10, 1000);
- _y_scale->SetRange (10, 1000);
- _line_spacing->SetRange (10, 1000);
+ _x_scale->SetRange (0, 1000);
+ _y_scale->SetRange (0, 1000);
+ _line_spacing->SetRange (0, 1000);
_reference->Bind (wxEVT_CHECKBOX, boost::bind (&TextPanel::reference_clicked, this));
_use->Bind (wxEVT_CHECKBOX, boost::bind (&TextPanel::use_toggled, this));
add_to_grid();
content_selection_changed ();
+
+ _sizer->Layout ();
}
+
void
TextPanel::setup_visibility ()
{
case TextType::OPEN_SUBTITLE:
if (_dcp_track_label) {
_dcp_track_label->Destroy ();
- _dcp_track_label = 0;
+ _dcp_track_label = nullptr;
}
if (_dcp_track) {
_dcp_track->Destroy ();
- _dcp_track = 0;
+ _dcp_track = nullptr;
}
if (!_outline_subtitles) {
_outline_subtitles = new CheckBox (this, _("Show subtitle area"));
_outline_subtitles->Bind (wxEVT_CHECKBOX, boost::bind (&TextPanel::outline_subtitles_changed, this));
_grid->Add (_outline_subtitles, wxGBPosition(_outline_subtitles_row, 0), wxGBSpan(1, 2));
}
-
+ if (!_language) {
+ _language_label = create_label (this, _("Language"), true);
+ add_label_to_sizer (_grid, _language_label, true, wxGBPosition(_ccap_track_or_language_row, 0));
+ _language_sizer = new wxBoxSizer (wxHORIZONTAL);
+ _language = new LanguageTagWidget (this, _("Language of these subtitles"), boost::none, wxString("en-US-"));
+ _language->Changed.connect (boost::bind(&TextPanel::language_changed, this));
+ _language_sizer->Add (_language->sizer(), 1, wxRIGHT, DCPOMATIC_SIZER_GAP);
+ _language_type = new wxChoice (this, wxID_ANY);
+ /// TRANSLATORS: Main and Additional here are a choice for whether a set of subtitles is in the "main" language of the
+ /// film or an "additional" language.
+ _language_type->Append (_("Main"));
+ _language_type->Append (_("Additional"));
+ _language_type->Bind (wxEVT_CHOICE, boost::bind(&TextPanel::language_is_additional_changed, this));
+ _language_sizer->Add (_language_type, 0, wxALIGN_CENTER_VERTICAL | wxTOP, DCPOMATIC_CHOICE_TOP_PAD);
+ _grid->Add (_language_sizer, wxGBPosition(_ccap_track_or_language_row, 1), wxGBSpan(1, 2));
+ film_content_changed (TextContentProperty::LANGUAGE);
+ film_content_changed (TextContentProperty::LANGUAGE_IS_ADDITIONAL);
+ }
break;
case TextType::CLOSED_CAPTION:
+ if (_language_label) {
+ _language_label->Destroy ();
+ _language_label = nullptr;
+ _grid->Remove (_language->sizer());
+ delete _language;
+ _grid->Remove (_language_sizer);
+ _language_sizer = nullptr;
+ _language = nullptr;
+ _language_type->Destroy ();
+ _language_type = nullptr;
+ }
if (!_dcp_track_label) {
_dcp_track_label = create_label (this, _("CCAP track"), true);
- add_label_to_sizer (_grid, _dcp_track_label, true, wxGBPosition(_ccap_track_row, 0));
+ add_label_to_sizer (_grid, _dcp_track_label, true, wxGBPosition(_ccap_track_or_language_row, 0));
}
if (!_dcp_track) {
_dcp_track = new wxChoice (this, wxID_ANY);
_dcp_track->Bind (wxEVT_CHOICE, boost::bind(&TextPanel::dcp_track_changed, this));
- _grid->Add (_dcp_track, wxGBPosition(_ccap_track_row, 1), wxDefaultSpan, wxEXPAND);
+ _grid->Add (_dcp_track, wxGBPosition(_ccap_track_or_language_row, 1), wxDefaultSpan, wxEXPAND);
update_dcp_tracks ();
film_content_changed (TextContentProperty::DCP_TRACK);
}
if (_outline_subtitles) {
_outline_subtitles->Destroy ();
- _outline_subtitles = 0;
+ _outline_subtitles = nullptr;
clear_outline_subtitles ();
}
break;
_grid->Layout ();
}
+
void
TextPanel::add_to_grid ()
{
{
add_label_to_sizer (_grid, _line_spacing_label, true, wxGBPosition (r, 0));
- wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ auto s = new wxBoxSizer (wxHORIZONTAL);
s->Add (_line_spacing);
add_label_to_sizer (s, _line_spacing_pc_label, false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
_grid->Add (s, wxGBPosition (r, 1));
++r;
}
- _ccap_track_row = r;
+ _ccap_track_or_language_row = r;
++r;
add_label_to_sizer (_grid, _stream_label, true, wxGBPosition (r, 0));
{
auto s = new wxBoxSizer (wxHORIZONTAL);
- s->Add (_text_view_button, 1, wxALL, DCPOMATIC_SIZER_GAP);
- s->Add (_fonts_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP);
- s->Add (_appearance_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP);
+ s->Add (_text_view_button, 0, wxALL, DCPOMATIC_SIZER_GAP);
+ s->Add (_fonts_dialog_button, 0, wxALL, DCPOMATIC_SIZER_GAP);
+ s->Add (_appearance_dialog_button, 0, wxALL, DCPOMATIC_SIZER_GAP);
- _grid->Add (s, wxGBPosition (r, 0), wxGBSpan (1, 2));
+ _grid->Add (s, wxGBPosition(r, 0), wxGBSpan(1, 2));
++r;
}
setup_visibility ();
}
+
void
TextPanel::update_dcp_track_selection ()
{
}
}
+
void
TextPanel::update_dcp_tracks ()
{
/* XXX: don't display the "magic" track which has empty name and language;
this is a nasty hack (see also Film::closed_caption_tracks)
*/
- if (!i.name.empty() || !i.language.empty()) {
+ if (!i.name.empty() || i.language) {
_dcp_track->Append (std_to_wx(i.summary()));
}
}
update_dcp_track_selection ();
}
+
void
TextPanel::dcp_track_changed ()
{
update_dcp_tracks ();
}
+
void
TextPanel::film_changed (Film::Property property)
{
}
}
+
void
TextPanel::film_content_changed (int property)
{
if (_dcp_track) {
update_dcp_track_selection ();
}
+ } else if (property == TextContentProperty::LANGUAGE) {
+ if (_language) {
+ _language->set (text ? text->language() : boost::none);
+ }
+ } else if (property == TextContentProperty::LANGUAGE_IS_ADDITIONAL) {
+ if (_language_type) {
+ _language_type->SetSelection (text ? (text->language_is_additional() ? 1 : 0) : 0);
+ }
} else if (property == DCPContentProperty::REFERENCE_TEXT) {
if (scs) {
auto dcp = dynamic_pointer_cast<DCPContent> (scs);
}
}
+
void
TextPanel::use_toggled ()
{
}
}
+
/** @return the text type that is currently selected in the drop-down */
TextType
TextPanel::current_type () const
return TextType::UNKNOWN;
}
+
void
TextPanel::type_changed ()
{
setup_visibility ();
}
+
void
TextPanel::burn_toggled ()
{
}
}
+
void
TextPanel::setup_sensitivity ()
{
auto sel = _parent->selected_text ();
for (auto i: sel) {
/* These are the content types that could include subtitles */
- auto fc = std::dynamic_pointer_cast<const FFmpegContent> (i);
- auto sc = std::dynamic_pointer_cast<const StringTextFileContent> (i);
- auto dc = std::dynamic_pointer_cast<const DCPContent> (i);
- auto dsc = std::dynamic_pointer_cast<const DCPSubtitleContent> (i);
+ auto fc = std::dynamic_pointer_cast<const FFmpegContent>(i);
+ auto sc = std::dynamic_pointer_cast<const StringTextFileContent>(i);
+ auto dc = std::dynamic_pointer_cast<const DCPContent>(i);
+ auto dsc = std::dynamic_pointer_cast<const DCPSubtitleContent>(i);
if (fc) {
if (!fc->text.empty()) {
++ffmpeg_subs;
shared_ptr<DCPContent> dcp;
if (sel.size() == 1) {
- dcp = dynamic_pointer_cast<DCPContent> (sel.front ());
+ dcp = dynamic_pointer_cast<DCPContent>(sel.front());
}
string why_not;
bool const reference = _reference->GetValue ();
- TextType const type = current_type ();
+ auto const type = current_type ();
/* Set up _type */
_type->Clear ();
_appearance_dialog_button->Enable (!reference && any_subs > 0 && use && type == TextType::OPEN_SUBTITLE);
}
+
void
TextPanel::stream_changed ()
{
auto a = fcs->subtitle_streams ();
auto i = a.begin ();
- auto const s = string_client_data (_stream->GetClientObject (_stream->GetSelection ()));
+ auto const s = string_client_data (_stream->GetClientObject(_stream->GetSelection()));
while (i != a.end() && (*i)->identifier () != s) {
++i;
}
}
}
+
void
TextPanel::x_offset_changed ()
{
}
}
+
void
TextPanel::y_offset_changed ()
{
}
}
+
void
TextPanel::x_scale_changed ()
{
}
}
+
void
TextPanel::y_scale_changed ()
{
}
}
+
void
TextPanel::line_spacing_changed ()
{
}
}
+
void
TextPanel::content_selection_changed ()
{
film_content_changed (TextContentProperty::FONTS);
film_content_changed (TextContentProperty::TYPE);
film_content_changed (TextContentProperty::DCP_TRACK);
+ film_content_changed (TextContentProperty::LANGUAGE);
+ film_content_changed (TextContentProperty::LANGUAGE_IS_ADDITIONAL);
film_content_changed (DCPContentProperty::REFERENCE_TEXT);
}
+
void
TextPanel::text_view_clicked ()
{
if (_text_view) {
_text_view->Destroy ();
- _text_view = 0;
+ _text_view = nullptr;
}
auto c = _parent->selected_text ();
}
}
+
void
TextPanel::fonts_dialog_clicked ()
{
_fonts_dialog->Show ();
}
+
void
TextPanel::reference_clicked ()
{
d->set_reference_text (_original_type, _reference->GetValue ());
}
+
void
TextPanel::appearance_dialog_clicked ()
{
}
-
/** The user has clicked on the outline subtitles check box */
void
TextPanel::outline_subtitles_changed ()
if (rect) {
auto content = _analysis_content.lock ();
DCPOMATIC_ASSERT (content);
- rect->x += content->text.front()->x_offset();
- rect->y += content->text.front()->y_offset();
+ rect->x += content->text.front()->x_offset() - _analysis->analysis_x_offset();
+ rect->y += content->text.front()->y_offset() - _analysis->analysis_y_offset();
}
fv->set_outline_subtitles (rect);
} else {
- fv->set_outline_subtitles (optional<dcpomatic::Rect<double> >());
+ fv->set_outline_subtitles ({});
}
}
try_to_load_analysis ();
}
+
+void
+TextPanel::language_changed ()
+{
+ for (auto i: _parent->selected_text()) {
+ auto t = i->text_of_original_type(_original_type);
+ if (t) {
+ t->set_language (_language->get());
+ }
+ }
+}
+
+
+void
+TextPanel::language_is_additional_changed ()
+{
+ for (auto i: _parent->selected_text()) {
+ auto t = i->text_of_original_type(_original_type);
+ if (t) {
+ t->set_language_is_additional (_language_type->GetSelection() == 1);
+ }
+ }
+}
+