2 Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 #include "full_language_tag_dialog.h"
23 #include "language_subtag_panel.h"
24 #include "subtag_list_ctrl.h"
25 #include "lib/dcpomatic_assert.h"
26 #include <dcp/language_tag.h>
27 #include <dcp/warnings.h>
28 LIBDCP_DISABLE_WARNINGS
29 #include <wx/listctrl.h>
30 #include <wx/srchctrl.h>
32 LIBDCP_ENABLE_WARNINGS
33 #include <boost/algorithm/string.hpp>
34 #include <boost/bind/bind.hpp>
35 #include <boost/optional.hpp>
36 #include <boost/signals2.hpp>
44 using std::shared_ptr;
48 using boost::optional;
49 #if BOOST_VERSION >= 106100
50 using namespace boost::placeholders;
54 FullLanguageTagDialog::FullLanguageTagDialog (wxWindow* parent, dcp::LanguageTag tag)
55 : wxDialog (parent, wxID_ANY, _("Language Tag"), wxDefaultPosition, wxSize(-1, 500))
57 _current_tag_list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER);
58 _current_tag_list->AppendColumn ("", wxLIST_FORMAT_LEFT, 200);
59 _current_tag_list->AppendColumn ("", wxLIST_FORMAT_LEFT, 400);
61 auto button_sizer = new wxBoxSizer (wxVERTICAL);
62 _add_script = new wxButton(this, wxID_ANY, "Add script");
63 button_sizer->Add (_add_script, 0, wxTOP | wxBOTTOM | wxEXPAND, 2);
64 _add_region = new wxButton(this, wxID_ANY, "Add region");
65 button_sizer->Add (_add_region, 0, wxTOP | wxBOTTOM | wxEXPAND, 2);
66 _add_variant = new wxButton(this, wxID_ANY, "Add variant");
67 button_sizer->Add (_add_variant, 0, wxTOP | wxBOTTOM | wxEXPAND, 2);
68 _add_external = new wxButton(this, wxID_ANY, "Add external");
69 button_sizer->Add (_add_external, 0, wxTOP | wxBOTTOM | wxEXPAND, 2);
70 _remove = new wxButton(this, wxID_ANY, "Remove");
71 button_sizer->Add (_remove, 0, wxTOP | wxBOTTOM | wxEXPAND, 2);
73 _choose_subtag_panel = new LanguageSubtagPanel (this);
74 _choose_subtag_panel->set (dcp::LanguageTag::SubtagType::LANGUAGE, "");
76 auto ltor_sizer = new wxBoxSizer (wxHORIZONTAL);
77 ltor_sizer->Add (_current_tag_list, 1, wxALL, 8);
78 ltor_sizer->Add (button_sizer, 0, wxALL, 8);
79 ltor_sizer->Add (_choose_subtag_panel, 1, wxALL, 8);
81 auto overall_sizer = new wxBoxSizer (wxVERTICAL);
82 overall_sizer->Add (ltor_sizer, 0);
84 auto buttons = CreateSeparatedButtonSizer (wxOK);
86 overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
89 SetSizerAndFit (overall_sizer);
93 _add_script->Bind (wxEVT_BUTTON, boost::bind(&FullLanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::SubtagType::SCRIPT, boost::optional<dcp::LanguageTag::SubtagData>()));
94 _add_region->Bind (wxEVT_BUTTON, boost::bind(&FullLanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::SubtagType::REGION, boost::optional<dcp::LanguageTag::SubtagData>()));
95 _add_variant->Bind (wxEVT_BUTTON, boost::bind(&FullLanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::SubtagType::VARIANT, boost::optional<dcp::LanguageTag::SubtagData>()));
96 _add_external->Bind (wxEVT_BUTTON, boost::bind(&FullLanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::SubtagType::EXTLANG, boost::optional<dcp::LanguageTag::SubtagData>()));
97 _remove->Bind (wxEVT_BUTTON, boost::bind(&FullLanguageTagDialog::remove_from_current_tag, this));
98 _choose_subtag_panel->SelectionChanged.connect(bind(&FullLanguageTagDialog::chosen_subtag_changed, this, _1));
99 _choose_subtag_panel->SearchChanged.connect(bind(&FullLanguageTagDialog::search_changed, this, _1));
100 _current_tag_list->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind(&FullLanguageTagDialog::current_tag_selection_changed, this));
101 _current_tag_list->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind(&FullLanguageTagDialog::current_tag_selection_changed, this));
106 FullLanguageTagDialog::remove_from_current_tag ()
108 auto selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
113 _current_tag_subtags.erase (_current_tag_subtags.begin() + selected);
114 _current_tag_list->DeleteItem (selected);
116 _current_tag_list->SetItemState (min(selected, _current_tag_list->GetItemCount() - 1L), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
118 setup_sensitivity ();
119 current_tag_selection_changed ();
123 dcp::LanguageTag FullLanguageTagDialog::get () const
125 dcp::LanguageTag tag;
127 vector<dcp::LanguageTag::VariantSubtag> variants;
128 vector<dcp::LanguageTag::ExtlangSubtag> extlangs;
130 for (auto i: _current_tag_subtags) {
135 case dcp::LanguageTag::SubtagType::LANGUAGE:
136 tag.set_language (i.subtag->subtag);
138 case dcp::LanguageTag::SubtagType::SCRIPT:
139 tag.set_script (i.subtag->subtag);
141 case dcp::LanguageTag::SubtagType::REGION:
142 tag.set_region (i.subtag->subtag);
144 case dcp::LanguageTag::SubtagType::VARIANT:
145 variants.push_back (i.subtag->subtag);
147 case dcp::LanguageTag::SubtagType::EXTLANG:
148 extlangs.push_back (i.subtag->subtag);
153 tag.set_variants (variants);
154 tag.set_extlangs (extlangs);
160 FullLanguageTagDialog::set (dcp::LanguageTag tag)
162 _current_tag_subtags.clear ();
163 _current_tag_list->DeleteAllItems ();
165 bool have_language = false;
166 for (auto const& i: tag.subtags()) {
167 add_to_current_tag (i.first, i.second);
168 if (i.first == dcp::LanguageTag::SubtagType::LANGUAGE) {
169 have_language = true;
173 if (!have_language) {
174 add_to_current_tag (dcp::LanguageTag::SubtagType::LANGUAGE, dcp::LanguageTag::SubtagData("en", "English"));
179 string FullLanguageTagDialog::subtag_type_name (dcp::LanguageTag::SubtagType type)
182 case dcp::LanguageTag::SubtagType::LANGUAGE:
184 case dcp::LanguageTag::SubtagType::SCRIPT:
186 case dcp::LanguageTag::SubtagType::REGION:
188 case dcp::LanguageTag::SubtagType::VARIANT:
190 case dcp::LanguageTag::SubtagType::EXTLANG:
199 FullLanguageTagDialog::search_changed (string search)
201 long int selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
203 _current_tag_subtags[selected].last_search = search;
209 FullLanguageTagDialog::add_to_current_tag (dcp::LanguageTag::SubtagType type, optional<dcp::LanguageTag::SubtagData> subtag)
211 _current_tag_subtags.push_back (Subtag(type, subtag));
213 it.SetId (_current_tag_list->GetItemCount());
215 it.SetText (subtag_type_name(type));
216 _current_tag_list->InsertItem (it);
219 it.SetText (subtag->description);
221 it.SetText ("Select...");
223 _current_tag_list->SetItem (it);
224 _current_tag_list->SetItemState (_current_tag_list->GetItemCount() - 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
225 _choose_subtag_panel->set (type, "");
226 setup_sensitivity ();
227 current_tag_selection_changed ();
232 FullLanguageTagDialog::current_tag_selection_changed ()
234 auto selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
236 _choose_subtag_panel->Enable (true);
237 _choose_subtag_panel->set (_current_tag_subtags[selected].type, _current_tag_subtags[selected].last_search, _current_tag_subtags[selected].subtag);
239 _choose_subtag_panel->Enable (false);
245 FullLanguageTagDialog::chosen_subtag_changed (optional<dcp::LanguageTag::SubtagData> selection)
251 auto selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
253 _current_tag_subtags[selected].subtag = *selection;
254 _current_tag_list->SetItem (selected, 0, subtag_type_name(_current_tag_subtags[selected].type));
255 _current_tag_list->SetItem (selected, 1, selection->description);
258 setup_sensitivity ();
262 FullLanguageTagDialog::setup_sensitivity ()
264 _add_script->Enable ();
265 _add_region->Enable ();
266 _add_variant->Enable ();
267 _add_external->Enable ();
268 for (auto const& i: _current_tag_subtags) {
270 case dcp::LanguageTag::SubtagType::SCRIPT:
271 _add_script->Enable (false);
273 case dcp::LanguageTag::SubtagType::REGION:
274 _add_region->Enable (false);
276 case dcp::LanguageTag::SubtagType::VARIANT:
277 _add_variant->Enable (false);
279 case dcp::LanguageTag::SubtagType::EXTLANG:
280 _add_external->Enable (false);
286 auto selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
287 _remove->Enable (selected > 0);