set completion pokemon

This commit is contained in:
sdine
2026-07-23 10:29:01 +02:00
parent ceb8605b5f
commit 16a5efb6b9
34 changed files with 2364 additions and 116 deletions
+3 -2
View File
@@ -36,8 +36,9 @@ public:
virtual wxPanel* selectedPanel(wxWindow* parent) = 0;
// When non-null, MainFrame mounts this as the sole content under the
// toolbar instead of the shared selected|list splitter. Digimon uses this
// for its Single Cards / Set Completion notebook. Default: no custom host.
// toolbar instead of the shared selected|list splitter. Digimon, Yu-Gi-Oh!,
// and Pokemon use this for Single Cards / Set Completion notebooks.
// Default: no custom host.
virtual wxPanel* contentPanel(wxWindow* parent) {
(void)parent;
return nullptr;
+45 -8
View File
@@ -1,7 +1,8 @@
#pragma once
// PokemonGameView: unified West + Asia Pokemon UI. One collection file;
// separate West/Asia set caches; Sets > Update Pokemon refreshes both.
// separate West/Asia set caches and set-completion catalogs. Sets > Update
// Pokemon refreshes both regions. Hosts Single Cards | Set Completion tabs.
#include "ccm/domain/PokemonCard.hpp"
#include "ccm/games/IGameModule.hpp"
@@ -9,17 +10,28 @@
#include "ccm/services/CollectionService.hpp"
#include "ccm/services/ConfigService.hpp"
#include "ccm/services/ImageService.hpp"
#include "ccm/services/PokemonSetCatalogService.hpp"
#include "ccm/services/SetService.hpp"
#include "ccm/ui/IGameView.hpp"
#include <array>
#include <string>
#include <string_view>
#include <vector>
class wxBitmapButton;
class wxBoxSizer;
class wxPanel;
class wxSimplebook;
class wxSplitterWindow;
class wxStaticText;
class wxTextCtrl;
namespace ccm::ui {
class PokemonCardListPanel;
class PokemonSelectedCardPanel;
class PokemonSetCompletionPanel;
class PokemonGameView final : public IGameView {
public:
@@ -28,13 +40,20 @@ public:
SetService& sets,
ImageService& images,
CardPreviewService& cardPreview,
IGameModule& module);
IGameModule& westModule,
IGameModule& asiaModule,
PokemonSetCatalogService& catalogStore);
[[nodiscard]] Game gameId() const noexcept override { return Game::Pokemon; }
[[nodiscard]] std::string displayName() const override { return "Pokemon"; }
wxPanel* listPanel(wxWindow* parent) override;
wxPanel* selectedPanel(wxWindow* parent) override;
wxPanel* contentPanel(wxWindow* parent) override;
[[nodiscard]] wxPanel* contentPanelIfCreated() const noexcept override {
return contentPanel_;
}
[[nodiscard]] bool hostsOwnLayout() const noexcept override { return true; }
void refreshCollection() override;
void onAddCard(wxWindow* parentWindow) override;
@@ -48,19 +67,37 @@ public:
private:
void ensureSetsLoaded();
const std::vector<Set>& setsForDialog(PokemonRegion region);
void ensureSingleCardsMounted(wxWindow* splitterParent);
void buildSingleCardsToolbar(wxWindow* parent, wxBoxSizer* pageSizer);
void buildTabBar(wxWindow* parent, wxBoxSizer* rootSizer);
void selectTab(int index);
void refreshToolbarIcons(const ThemePalette& palette);
void refreshTabBarTheme(const ThemePalette& palette);
ConfigService& config_;
CollectionService<PokemonCard>& collection_;
SetService& sets_;
ImageService& images_;
CardPreviewService& cardPreview_;
IGameModule& module_;
IGameModule& westModule_;
IGameModule& asiaModule_;
PokemonSetCatalogService& catalogStore_;
PokemonCardListPanel* listPanel_{nullptr};
PokemonSelectedCardPanel* selectedPanel_{nullptr};
std::vector<Set> setsCacheWest_;
std::vector<Set> setsCacheAsia_;
bool attemptedInitialSetLoad_{false};
wxPanel* contentPanel_{nullptr};
wxPanel* tabBar_{nullptr};
wxSimplebook* book_{nullptr};
wxSplitterWindow* singleSplitter_{nullptr};
PokemonCardListPanel* listPanel_{nullptr};
PokemonSelectedCardPanel* selectedPanel_{nullptr};
PokemonSetCompletionPanel* setCompletionPanel_{nullptr};
std::array<wxPanel*, 2> tabPanels_{{nullptr, nullptr}};
std::array<wxStaticText*, 2> tabLabels_{{nullptr, nullptr}};
int activeTab_{0};
std::array<wxBitmapButton*, 3> toolbarButtons_{{nullptr, nullptr, nullptr}};
wxTextCtrl* filterInput_{nullptr};
std::vector<Set> setsCacheWest_;
std::vector<Set> setsCacheAsia_;
bool attemptedInitialSetLoad_{false};
};
} // namespace ccm::ui
@@ -0,0 +1,81 @@
#pragma once
// PokemonSetCompletionPanel: Set Completion tab — pack tiles with progress
// bars for sets the user owns ≥1 card of, plus an in-tab checklist drill-down
// (unowned rows greyed). Dual offline catalogs (West + Asia). Optional region
// and language filters restrict ownership; set titles may be annotated with
// region and/or language.
#include "ccm/domain/Enums.hpp"
#include "ccm/domain/PokemonCard.hpp"
#include "ccm/domain/PokemonSetCatalog.hpp"
#include "ccm/services/PokemonSetCatalogService.hpp"
#include "ccm/ui/Theme.hpp"
#include <wx/panel.h>
#include <optional>
#include <string>
#include <vector>
class wxBoxSizer;
class wxChoice;
class wxListCtrl;
class wxScrolledWindow;
class wxSimplebook;
class wxStaticText;
namespace ccm::ui {
class PokemonSetCompletionPanel : public wxPanel {
public:
PokemonSetCompletionPanel(wxWindow* parent, PokemonSetCatalogService& catalogStore);
void setCollection(std::vector<PokemonCard> cards);
void reloadFromStore();
void applyTheme(const ThemePalette& palette);
private:
void showGridPage();
void showChecklistPage(PokemonRegion region, const std::string& setId,
const std::string& setName);
void rebuildGrid();
void rebuildChecklist(PokemonRegion region, const std::string& setId);
void setEmptyMessage(const wxString& message);
void clearGridTiles();
void refreshRegionChoice();
void refreshLanguageChoice();
void onRegionChoice(wxCommandEvent& event);
void onLanguageChoice(wxCommandEvent& event);
void rebuildCurrentView();
[[nodiscard]] std::string displaySetName(const std::string& setName,
PokemonRegion region) const;
[[nodiscard]] bool catalogsReadyForFilter() const;
PokemonSetCatalogService& catalogStore_;
PokemonSetCatalog westCatalog_;
PokemonSetCatalog asiaCatalog_;
bool westCatalogLoaded_{false};
bool asiaCatalogLoaded_{false};
std::vector<PokemonCard> collection_;
ThemePalette palette_{};
std::optional<PokemonRegion> regionFilter_;
std::optional<Language> languageFilter_;
wxChoice* regionChoice_{nullptr};
wxChoice* languageChoice_{nullptr};
wxSimplebook* book_{nullptr};
wxPanel* gridPage_{nullptr};
wxScrolledWindow* scroll_{nullptr};
wxBoxSizer* gridSizer_{nullptr};
wxStaticText* emptyLabel_{nullptr};
wxPanel* detailPage_{nullptr};
wxStaticText* detailTitle_{nullptr};
wxListCtrl* checklist_{nullptr};
PokemonRegion detailRegion_{PokemonRegion::West};
std::string detailSetId_;
std::string detailSetName_;
};
} // namespace ccm::ui