#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);