X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fwx%2Flanguage_tag_dialog.cc;h=ca08996c681d01a5d2c47b24ecbfd9000948316b;hb=c76a7e968f54eb0e6c8da9c1ae6bc069ed05fdda;hp=94e266f2c5b88e2a4e601fc5b528632ba54eb84b;hpb=e519feaca11005d330e7b8403b948d4ad9cc3ae8;p=dcpomatic.git diff --git a/src/wx/language_tag_dialog.cc b/src/wx/language_tag_dialog.cc index 94e266f2c..ca08996c6 100644 --- a/src/wx/language_tag_dialog.cc +++ b/src/wx/language_tag_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington + Copyright (C) 2021 Carl Hetherington This file is part of DCP-o-matic. @@ -19,434 +19,133 @@ */ -#include "lib/dcpomatic_assert.h" +#include "full_language_tag_dialog.h" #include "language_tag_dialog.h" -#include +#include "wx_util.h" +#include "lib/config.h" #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using std::min; -using std::pair; -using std::string; -using std::vector; -using boost::optional; -using boost::shared_ptr; -using boost::weak_ptr; -#if BOOST_VERSION >= 106100 -using namespace boost::placeholders; -#endif - - -class SubtagListCtrl : public wxListCtrl -{ -public: - SubtagListCtrl (wxWindow* parent) - : wxListCtrl (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxLC_VIRTUAL) - { - AppendColumn ("", wxLIST_FORMAT_LEFT, 80); - AppendColumn ("", wxLIST_FORMAT_LEFT, 400); - } - - void set (dcp::LanguageTag::SubtagType type, string search, optional subtag = optional()) - { - _all_subtags = dcp::LanguageTag::get_all(type); - set_search (search); - if (subtag) { - vector::iterator i = find(_matching_subtags.begin(), _matching_subtags.end(), *subtag); - if (i != _matching_subtags.end()) { - long item = std::distance(_matching_subtags.begin(), i); - SetItemState (item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); - EnsureVisible (item); - } - } else { - if (GetItemCount() > 0) { - /* The new list sometimes isn't visible without this */ - EnsureVisible (0); - } - } - } - - void set_search (string search) - { - if (search == "") { - _matching_subtags = _all_subtags; - } else { - _matching_subtags.clear (); - - boost::algorithm::to_lower(search); - BOOST_FOREACH (dcp::LanguageTag::SubtagData const& i, _all_subtags) { - if ( - (boost::algorithm::to_lower_copy(i.subtag).find(search) != string::npos) || - (boost::algorithm::to_lower_copy(i.description).find(search) != string::npos)) { - _matching_subtags.push_back (i); - } - } - } - - SetItemCount (_matching_subtags.size()); - if (GetItemCount() > 0) { - RefreshItems (0, GetItemCount() - 1); - } - } - - optional selected_subtag () const - { - long int selected = GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - if (selected == -1) { - return optional(); - } +#include - DCPOMATIC_ASSERT (static_cast(selected) < _matching_subtags.size()); - return _matching_subtags[selected]; - } -private: - wxString OnGetItemText (long item, long column) const - { - if (column == 0) { - return _matching_subtags[item].subtag; - } else { - return _matching_subtags[item].description; - } - } - - std::vector _all_subtags; - std::vector _matching_subtags; -}; +using std::vector; -class LanguageSubtagPanel : public wxPanel +LanguageTagDialog::LanguageTagDialog (wxWindow* parent, dcp::LanguageTag tag) + : wxDialog (parent, wxID_ANY, _("Language Tag")) { -public: - LanguageSubtagPanel (wxWindow* parent) - : wxPanel (parent, wxID_ANY) - { -#ifdef __WXGTK3__ - int const height = 30; -#else - int const height = -1; -#endif - - _search = new wxSearchCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200, height)); - _list = new SubtagListCtrl (this); - - wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL); - sizer->Add (_search, 0, wxALL, 8); - sizer->Add (_list, 1, wxALL, 8); - SetSizer (sizer); - - _search->Bind (wxEVT_TEXT, boost::bind(&LanguageSubtagPanel::search_changed, this)); - _list->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind(&LanguageSubtagPanel::selection_changed, this)); - _list->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind(&LanguageSubtagPanel::selection_changed, this)); - } + _list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize(600, 700), wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER); + _list->AppendColumn ("", wxLIST_FORMAT_LEFT, 400); + _list->AppendColumn ("", wxLIST_FORMAT_LEFT, 150); + auto add = new wxButton (this, wxID_ANY, _("Add language...")); - void set (dcp::LanguageTag::SubtagType type, string search, optional subtag = optional()) - { - _list->set (type, search, subtag); - _search->SetValue (wxString(search)); - } - - optional get () const - { - if (!_list->selected_subtag()) { - return optional(); - } + auto overall_sizer = new wxBoxSizer (wxVERTICAL); + overall_sizer->Add (_list, 0, wxALL, DCPOMATIC_SIZER_GAP); + overall_sizer->Add (add, 0, wxALL, DCPOMATIC_SIZER_GAP); - return dcp::LanguageTag::RegionSubtag(_list->selected_subtag()->subtag); - } - - boost::signals2::signal)> SelectionChanged; - boost::signals2::signal SearchChanged; - -private: - void search_changed () - { - _list->set_search (_search->GetValue().ToStdString()); - SearchChanged (_search->GetValue().ToStdString()); - } - - void selection_changed () - { - SelectionChanged (_list->selected_subtag()); - } - - wxSearchCtrl* _search; - SubtagListCtrl* _list; -}; - - -LanguageTagDialog::LanguageTagDialog (wxWindow* parent, dcp::LanguageTag tag) - : wxDialog (parent, wxID_ANY, "Language Tag", wxDefaultPosition, wxSize(-1, 500)) -{ - _current_tag_list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER); - _current_tag_list->AppendColumn ("", wxLIST_FORMAT_LEFT, 200); - _current_tag_list->AppendColumn ("", wxLIST_FORMAT_LEFT, 400); - - wxBoxSizer* button_sizer = new wxBoxSizer (wxVERTICAL); - _add_script = new wxButton(this, wxID_ANY, "Add script"); - button_sizer->Add (_add_script, 0, wxTOP | wxBOTTOM | wxEXPAND, 2); - _add_region = new wxButton(this, wxID_ANY, "Add region"); - button_sizer->Add (_add_region, 0, wxTOP | wxBOTTOM | wxEXPAND, 2); - _add_variant = new wxButton(this, wxID_ANY, "Add variant"); - button_sizer->Add (_add_variant, 0, wxTOP | wxBOTTOM | wxEXPAND, 2); - _add_external = new wxButton(this, wxID_ANY, "Add external"); - button_sizer->Add (_add_external, 0, wxTOP | wxBOTTOM | wxEXPAND, 2); - _remove = new wxButton(this, wxID_ANY, "Remove"); - button_sizer->Add (_remove, 0, wxTOP | wxBOTTOM | wxEXPAND, 2); - - _choose_subtag_panel = new LanguageSubtagPanel (this); - _choose_subtag_panel->set (dcp::LanguageTag::LANGUAGE, ""); - - wxBoxSizer* ltor_sizer = new wxBoxSizer (wxHORIZONTAL); - ltor_sizer->Add (_current_tag_list, 1, wxALL, 8); - ltor_sizer->Add (button_sizer, 0, wxALL, 8); - ltor_sizer->Add (_choose_subtag_panel, 1, wxALL, 8); - - wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); - overall_sizer->Add (ltor_sizer, 0); - - wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); + auto buttons = CreateSeparatedButtonSizer (wxOK); if (buttons) { overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); } SetSizerAndFit (overall_sizer); - set (tag); - - _add_script->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::SCRIPT, boost::optional())); - _add_region->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::REGION, boost::optional())); - _add_variant->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::VARIANT, boost::optional())); - _add_external->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::EXTLANG, boost::optional())); - _remove->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::remove_from_current_tag, this)); - _choose_subtag_panel->SelectionChanged.connect(bind(&LanguageTagDialog::chosen_subtag_changed, this, _1)); - _choose_subtag_panel->SearchChanged.connect(bind(&LanguageTagDialog::search_changed, this, _1)); - _current_tag_list->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind(&LanguageTagDialog::current_tag_selection_changed, this)); - _current_tag_list->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind(&LanguageTagDialog::current_tag_selection_changed, this)); -} - - -void -LanguageTagDialog::remove_from_current_tag () -{ - long int selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - if (selected <= 0) { - return; + for (auto const& i: dcp::dcnc_tags()) { + _presets.push_back (dcp::LanguageTag(i.first)); } - _current_tag_subtags.erase (_current_tag_subtags.begin() + selected); - _current_tag_list->DeleteItem (selected); + std::sort (_presets.begin(), _presets.end(), [](dcp::LanguageTag const& i, dcp::LanguageTag const& j) { + return i.description() < j.description(); + }); - _current_tag_list->SetItemState (min(selected, _current_tag_list->GetItemCount() - 1L), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + _custom = Config::instance()->custom_languages (); - setup_sensitivity (); - current_tag_selection_changed (); -} - - -dcp::LanguageTag LanguageTagDialog::get () const -{ - dcp::LanguageTag tag; + populate_list (); - vector variants; - vector extlangs; - - BOOST_FOREACH (Subtag i, _current_tag_subtags) { - if (!i.subtag) { - continue; - } - switch (i.type) { - case dcp::LanguageTag::LANGUAGE: - tag.set_language (i.subtag->subtag); - break; - case dcp::LanguageTag::SCRIPT: - tag.set_script (i.subtag->subtag); - break; - case dcp::LanguageTag::REGION: - tag.set_region (i.subtag->subtag); - break; - case dcp::LanguageTag::VARIANT: - variants.push_back (i.subtag->subtag); - break; - case dcp::LanguageTag::EXTLANG: - extlangs.push_back (i.subtag->subtag); - break; - } - } + set (tag); - tag.set_variants (variants); - tag.set_extlangs (extlangs); - return tag; + add->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_language, this)); } void -LanguageTagDialog::set (dcp::LanguageTag tag) +LanguageTagDialog::add_language () { - _current_tag_subtags.clear (); - _current_tag_list->DeleteAllItems (); - - bool have_language = false; - vector > subtags = tag.subtags(); - for (vector >::const_iterator i = subtags.begin(); i != subtags.end(); ++i) { - add_to_current_tag (i->first, i->second); - if (i->first == dcp::LanguageTag::LANGUAGE) { - have_language = true; - } - } - - if (!have_language) { - add_to_current_tag (dcp::LanguageTag::LANGUAGE, dcp::LanguageTag::SubtagData("en", "English")); + auto full = new FullLanguageTagDialog (GetParent()); + auto r = full->ShowModal (); + if (r == wxID_OK) { + Config::instance()->add_custom_language (full->get()); + set (full->get()); } -} - - -string LanguageTagDialog::subtag_type_name (dcp::LanguageTag::SubtagType type) -{ - switch (type) { - case dcp::LanguageTag::LANGUAGE: - return "Language"; - case dcp::LanguageTag::SCRIPT: - return "Script"; - case dcp::LanguageTag::REGION: - return "Region"; - case dcp::LanguageTag::VARIANT: - return "Variant"; - case dcp::LanguageTag::EXTLANG: - return "External"; - } - - return ""; + full->Destroy (); } void -LanguageTagDialog::search_changed (string search) +LanguageTagDialog::populate_list () { - long int selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - if (selected >= 0) { - _current_tag_subtags[selected].last_search = search; - } -} - + _list->DeleteAllItems (); + + auto add = [this](vector const& tags) { + for (auto const& i: tags) { + wxListItem it; + it.SetId (_list->GetItemCount()); + it.SetColumn (0); + it.SetText (std_to_wx(i.description())); + _list->InsertItem (it); + it.SetColumn (1); + it.SetText (std_to_wx(i.to_string())); + _list->SetItem (it); + } + }; -void -LanguageTagDialog::add_to_current_tag (dcp::LanguageTag::SubtagType type, optional subtag) -{ - _current_tag_subtags.push_back (Subtag(type, subtag)); - wxListItem it; - it.SetId (_current_tag_list->GetItemCount()); - it.SetColumn (0); - it.SetText (subtag_type_name(type)); - _current_tag_list->InsertItem (it); - it.SetColumn (1); - if (subtag) { - it.SetText (subtag->description); - } else { - it.SetText ("Select..."); - } - _current_tag_list->SetItem (it); - _current_tag_list->SetItemState (_current_tag_list->GetItemCount() - 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); - _choose_subtag_panel->set (type, ""); - setup_sensitivity (); - current_tag_selection_changed (); + add (_presets); + add (_custom); } void -LanguageTagDialog::current_tag_selection_changed () +LanguageTagDialog::set (dcp::LanguageTag tag) { - long int selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - if (selected >= 0) { - _choose_subtag_panel->Enable (true); - _choose_subtag_panel->set (_current_tag_subtags[selected].type, _current_tag_subtags[selected].last_search, _current_tag_subtags[selected].subtag); + size_t selection = 0; + + auto iter = find(_presets.begin(), _presets.end(), tag); + if (iter == _presets.end()) { + iter = find(_custom.begin(), _custom.end(), tag); + if (iter == _custom.end()) { + _custom.push_back (tag); + selection = _presets.size() + _custom.size() - 1; + populate_list (); + if (_list->GetItemCount() > 0) { + _list->EnsureVisible (_list->GetItemCount() - 1); + } + } else { + selection = _presets.size() + std::distance(_custom.begin(), iter); + } } else { - _choose_subtag_panel->Enable (false); + selection = std::distance(_presets.begin(), iter); } -} - -void -LanguageTagDialog::chosen_subtag_changed (optional selection) -{ - if (!selection) { - return; + _list->SetItemState (selection, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + if (static_cast(selection) < _list->GetItemCount()) { + _list->EnsureVisible (selection); } - - long int selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - if (selected >= 0) { - _current_tag_subtags[selected].subtag = *selection; - _current_tag_list->SetItem (selected, 0, subtag_type_name(_current_tag_subtags[selected].type)); - _current_tag_list->SetItem (selected, 1, selection->description); - } - - setup_sensitivity (); -} - -void -LanguageTagDialog::setup_sensitivity () -{ - _add_script->Enable (); - _add_region->Enable (); - _add_variant->Enable (); - _add_external->Enable (); - BOOST_FOREACH (Subtag const& i, _current_tag_subtags) { - switch (i.type) { - case dcp::LanguageTag::SCRIPT: - _add_script->Enable (false); - break; - case dcp::LanguageTag::REGION: - _add_region->Enable (false); - break; - case dcp::LanguageTag::VARIANT: - _add_variant->Enable (false); - break; - case dcp::LanguageTag::EXTLANG: - _add_external->Enable (false); - break; - default: - break; - } - } - long int selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - _remove->Enable (selected > 0); } -RegionSubtagDialog::RegionSubtagDialog (wxWindow* parent, dcp::LanguageTag::RegionSubtag region) - : wxDialog (parent, wxID_ANY, _("Region"), wxDefaultPosition, wxSize(-1, 500)) - , _panel (new LanguageSubtagPanel (this)) +dcp::LanguageTag +LanguageTagDialog::get () const { - wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL); - sizer->Add (_panel, 1); + auto selected = _list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + DCPOMATIC_ASSERT (selected >= 0); - wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); - if (buttons) { - sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); + if (selected < static_cast(_presets.size())) { + return _presets[selected]; } - SetSizer (sizer); - - _panel->set (dcp::LanguageTag::REGION, "", *dcp::LanguageTag::get_subtag_data(region)); -} - + selected -= _presets.size(); -optional -RegionSubtagDialog::get () const -{ - return _panel->get (); + DCPOMATIC_ASSERT (selected < static_cast(_custom.size())); + return _custom[selected]; } -