From: Carl Hetherington Date: Sun, 23 Aug 2020 20:08:00 +0000 (+0200) Subject: DROPME: add test wxWidgets UI for LanguageTag editing. X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=b3dc4d260bc839e677013b620f70be867bd97905;p=libdcp.git DROPME: add test wxWidgets UI for LanguageTag editing. --- diff --git a/langtest.cc b/langtest.cc new file mode 100644 index 00000000..bad4a0d8 --- /dev/null +++ b/langtest.cc @@ -0,0 +1,350 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using std::string; +using std::vector; +using boost::enable_shared_from_this; +using boost::optional; +using boost::shared_ptr; +using boost::weak_ptr; + + +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_type_and_search (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()) { + SetItemState (std::distance(_matching_subtags.begin(), i), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + } + } + } + + void set_search (string search) + { + if (search == "") { + _matching_subtags = _all_subtags; + } else { + _matching_subtags.clear (); + + boost::algorithm::to_lower(search); + BOOST_FOREACH (dcp::LanguageTag::Subtag 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(); + } + + //DCPOMATIC_ASSERT (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; +}; + + +class LanguageSubtagPanel : public wxPanel +{ +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); + SetSizerAndFit (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)); + } + + void set_type_and_search (dcp::LanguageTag::SubtagType type, string search, optional subtag = optional()) + { + _list->set_type_and_search (type, search, subtag); + _search->SetValue (wxString(search)); + } + + 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; +}; + + + + +class LanguageTagDialog : public wxDialog +{ +public: + class Subtag + { + public: + Subtag (dcp::LanguageTag::SubtagType type_, dcp::LanguageTag::Subtag subtag_) + : type (type_) + , subtag (subtag_) + {} + + dcp::LanguageTag::SubtagType type; + dcp::LanguageTag::Subtag subtag; + std::string last_search; + }; + + LanguageTagDialog (wxWindow* parent) + : wxDialog (parent, wxID_ANY, "Language Tag") + { + _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, 1, wxTOP | wxBOTTOM | wxEXPAND, 2); + _add_region = new wxButton(this, wxID_ANY, "Add region"); + button_sizer->Add (_add_region, 1, wxTOP | wxBOTTOM | wxEXPAND, 2); + _add_variant = new wxButton(this, wxID_ANY, "Add variant"); + button_sizer->Add (_add_variant, 1, wxTOP | wxBOTTOM | wxEXPAND, 2); + _add_external = new wxButton(this, wxID_ANY, "Add external"); + button_sizer->Add (_add_external, 1, wxTOP | wxBOTTOM | wxEXPAND, 2); + + _choose_subtag_panel = new LanguageSubtagPanel (this); + _choose_subtag_panel->set_type_and_search (dcp::LanguageTag::LANGUAGE, "de"); + + wxBoxSizer* overall_sizer = new wxBoxSizer (wxHORIZONTAL); + overall_sizer->Add (_current_tag_list, 1, wxALL, 8); + overall_sizer->Add (button_sizer, 0, wxALL, 8); + overall_sizer->Add (_choose_subtag_panel, 1, wxALL, 8); + + SetSizerAndFit (overall_sizer); + + add_to_current_tag (dcp::LanguageTag::LANGUAGE, dcp::LanguageTag::Subtag("en", "English")); + + _add_script->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::SCRIPT, dcp::LanguageTag::Subtag())); + _add_region->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::REGION, dcp::LanguageTag::Subtag())); + _add_variant->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::VARIANT, dcp::LanguageTag::Subtag())); + _add_external->Bind (wxEVT_BUTTON, boost::bind(&LanguageTagDialog::add_to_current_tag, this, dcp::LanguageTag::EXTLANG, dcp::LanguageTag::Subtag())); + _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)); + } + + dcp::LanguageTag get () const + { + dcp::LanguageTag tag; + + vector variants; + vector extlangs; + + BOOST_FOREACH (Subtag i, _current_tag_subtags) { + 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; + } + } + + tag.set_variants (variants); + tag.set_extlangs (extlangs); + return tag; + } + + +private: + + string 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 ""; + } + + void search_changed (string search) + { + long int selected = _current_tag_list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (selected >= 0) { + _current_tag_subtags[selected].last_search = search; + } + } + + void add_to_current_tag (dcp::LanguageTag::SubtagType type, dcp::LanguageTag::Subtag 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); + 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_and_search (type, ""); + setup_sensitivity (); + } + + void current_tag_selection_changed () + { + 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_type_and_search (_current_tag_subtags[selected].type, _current_tag_subtags[selected].last_search, _current_tag_subtags[selected].subtag); + } else { + _choose_subtag_panel->Enable (false); + } + } + + void chosen_subtag_changed (optional selection) + { + if (!selection) { + return; + } + + 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); + } + } + + void 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; + } + } + } + + vector _current_tag_subtags; + wxListCtrl* _current_tag_list; + LanguageSubtagPanel* _choose_subtag_panel; + wxButton* _add_script; + wxButton* _add_region; + wxButton* _add_variant; + wxButton* _add_external; +}; + + +class MyApp : public wxApp +{ +public: + virtual bool OnInit() + { + LanguageTagDialog* dialog = new LanguageTagDialog (0); + dialog->ShowModal (); + return true; + } +}; + +wxIMPLEMENT_APP(MyApp); + diff --git a/langtest.sh b/langtest.sh new file mode 100644 index 00000000..56116837 --- /dev/null +++ b/langtest.sh @@ -0,0 +1 @@ +g++ -g -o langtest langtest.cc `wx-config --cflags --libs` -I. -Lbuild/src -ldcp-1.0