mirror of
https://github.com/sebastiandine/Card-Collection-Manager-3.git
synced 2026-09-03 11:18:49 +00:00
Minor: Add Asian Pokemon Card Support (#18)
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
// BaseCardEditDialog<TCard>
|
||||
//
|
||||
// Header-only template for the modal create/edit form. Owns the parts every
|
||||
// game shares — Name, Set picker (read-only combo with prefix typeahead),
|
||||
// game shares — Name, Set picker (read-only combo with typeahead: prefix first,
|
||||
// then substring, with ASCII-fold so "Pokemon"/"Jungle" match "Pokémon Jungle"),
|
||||
// Amount spin, Language and Condition choices, Note, Image list with
|
||||
// Add/Remove/double-click-to-view, OK/Cancel — and exposes hooks the
|
||||
// subclass uses to:
|
||||
@@ -48,6 +49,7 @@
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -102,6 +104,9 @@ protected:
|
||||
// wants; the base only owns the surrounding label.
|
||||
virtual void buildFlagsRow(wxBoxSizer* flagsBox) = 0;
|
||||
|
||||
// Subclass adds any labelled rows between Name and Set. Default does nothing.
|
||||
virtual void appendPreSetRows(wxFlexGridSizer* /*grid*/) {}
|
||||
|
||||
// Subclass adds any extra game-specific labelled rows just below the
|
||||
// standard rows but above the Note row, by calling `appendRow(label, ctrl)`
|
||||
// (provided as a parameter). Default does nothing.
|
||||
@@ -114,6 +119,11 @@ protected:
|
||||
// Subclass copies the extra fields it owns from its widgets back into `card_`.
|
||||
virtual void writeExtraToCard() {}
|
||||
|
||||
// Languages offered in the Language choice. Default: allLanguages().
|
||||
[[nodiscard]] virtual std::span<const Language> languagesForChoice() const {
|
||||
return allLanguages();
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual std::string updateMenuName() const { return "Update Sets"; }
|
||||
|
||||
// Display name passed into errors and the dialog title hints.
|
||||
@@ -151,6 +161,12 @@ protected:
|
||||
return preloadedSets_ != nullptr ? *preloadedSets_ : sets_;
|
||||
}
|
||||
|
||||
void setPreloadedSetsPointer(const std::vector<Set>* sets) noexcept {
|
||||
preloadedSets_ = sets;
|
||||
}
|
||||
|
||||
void refreshSetAndLanguageChoices() { populateChoices(); }
|
||||
|
||||
// Default: combo only. Yu-Gi-Oh! overrides to add set-code entry + toggle.
|
||||
virtual void customizeSetPickerRow(wxBoxSizer& row, wxComboBox* combo) {
|
||||
row.Add(combo, 1, wxEXPAND);
|
||||
@@ -193,6 +209,9 @@ private:
|
||||
});
|
||||
appendRow(grid, "Name", nameCtrl_);
|
||||
|
||||
// Optional rows between Name and Set (e.g. Pokemon West/Asia region).
|
||||
appendPreSetRows(grid);
|
||||
|
||||
// `setCombo_` must be parented to `setHost` so every control in the Set row
|
||||
// shares the same `wxPanel`; otherwise the combo stays a direct child of the
|
||||
// dialog while the sizer lives on `setHost`, which corrupts layout on MSW.
|
||||
@@ -311,9 +330,10 @@ private:
|
||||
languageChoice_->Clear();
|
||||
int langIdx = 0;
|
||||
int i = 0;
|
||||
const auto langsForChoice = languagesForChoice();
|
||||
wxArrayString langs;
|
||||
langs.Alloc(allLanguages().size());
|
||||
for (auto l : allLanguages()) {
|
||||
langs.Alloc(langsForChoice.size());
|
||||
for (auto l : langsForChoice) {
|
||||
const std::string lang = std::string(to_string(l));
|
||||
langs.Add(wxString::FromUTF8(lang.c_str()));
|
||||
if (l == card_.language) langIdx = i;
|
||||
@@ -486,20 +506,43 @@ private:
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fold a few Latin-1 diacritics so typing ASCII "Pokemon" matches "Pokémon".
|
||||
[[nodiscard]] static wxString foldAsciiForTypeahead(wxString s) {
|
||||
s.MakeLower();
|
||||
s.Replace(wxString::FromUTF8("\xc3\xa9"), wxT("e")); // é
|
||||
s.Replace(wxString::FromUTF8("\xc3\x89"), wxT("e")); // É (after lower: é)
|
||||
s.Replace(wxString::FromUTF8("\xc3\xa8"), wxT("e")); // è
|
||||
s.Replace(wxString::FromUTF8("\xc3\xaa"), wxT("e")); // ê
|
||||
s.Replace(wxString::FromUTF8("\xc3\xa0"), wxT("a")); // à
|
||||
s.Replace(wxString::FromUTF8("\xc3\xa1"), wxT("a")); // á
|
||||
s.Replace(wxString::FromUTF8("\xc3\xb1"), wxT("n")); // ñ
|
||||
s.Replace(wxString::FromUTF8("\xc3\xbc"), wxT("u")); // ü
|
||||
s.Replace(wxString::FromUTF8("\xc3\xb6"), wxT("o")); // ö
|
||||
return s;
|
||||
}
|
||||
|
||||
void applySetTypeaheadSelection() {
|
||||
const auto& available = availableSets();
|
||||
if (!setCombo_ || available.empty()) return;
|
||||
wxString pref = setTypeaheadPrefix_;
|
||||
pref.MakeLower();
|
||||
const wxString pref = foldAsciiForTypeahead(setTypeaheadPrefix_);
|
||||
if (pref.empty()) return;
|
||||
// Prefer prefix matches, then substring (so "Jungle" finds "Pokémon Jungle").
|
||||
for (std::size_t i = 0; i < available.size(); ++i) {
|
||||
wxString name(wxString::FromUTF8(available[i].name));
|
||||
name.MakeLower();
|
||||
const wxString name =
|
||||
foldAsciiForTypeahead(wxString::FromUTF8(available[i].name));
|
||||
if (name.StartsWith(pref)) {
|
||||
setCombo_->SetSelection(static_cast<int>(i));
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (std::size_t i = 0; i < available.size(); ++i) {
|
||||
const wxString name =
|
||||
foldAsciiForTypeahead(wxString::FromUTF8(available[i].name));
|
||||
if (name.Contains(pref)) {
|
||||
setCombo_->SetSelection(static_cast<int>(i));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onSetComboChar(wxKeyEvent& ev) {
|
||||
|
||||
Reference in New Issue
Block a user