initial commit
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include "page.h"
|
||||
#include "db/database_manager.h"
|
||||
#include "text_cache.h"
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// The always-on top-level proclamation. It can neither be selected nor
|
||||
// deselected, is never shown inside a category, and is always flagged as
|
||||
// selected in the database. Set this to the correct proclamation ID.
|
||||
constexpr const char* DEFAULT_PROPLEAMATION_ID = "f3d42354-3197-45e4-9b08-be447f14386d";
|
||||
|
||||
// Display name used for the always-on top-level proclamation.
|
||||
constexpr const char* DEFAULT_PROPLEAMATION_NAME = "Synchronize, Harmonize & Energize";
|
||||
|
||||
class ProclamationOptionsPage : public Page {
|
||||
public:
|
||||
void onPush(AppState& state) override;
|
||||
void onResume(AppState& state) override;
|
||||
void onPause(AppState& state) override;
|
||||
void onPop(AppState& state) override;
|
||||
void handleEvent(const SDL_Event& event) override;
|
||||
void update(float dt) override;
|
||||
void render(SDL_Renderer* renderer) override;
|
||||
|
||||
private:
|
||||
struct FlatItem {
|
||||
enum class Type { RootCategory, SubCategory, Proclamation };
|
||||
|
||||
Type type = Type::Proclamation;
|
||||
std::string id; // category id or proclamation id
|
||||
std::string label; // display text
|
||||
int depth = 0; // 0 = root category / default, 1 = sub-category, 2 = proclamation
|
||||
bool expanded = false; // categories only
|
||||
bool selected = false; // proclamations only
|
||||
bool isDefault = false; // the always-on top-level proclamation
|
||||
};
|
||||
|
||||
void loadFromDb();
|
||||
void rebuildItems();
|
||||
void rebuildVisible();
|
||||
void toggleItem();
|
||||
void toggleSearchItem();
|
||||
void collapseCurrent();
|
||||
void expandCurrent();
|
||||
void moveToParent();
|
||||
void saveSelectionToDb();
|
||||
void clearAllSelections();
|
||||
void ensureHighlightVisible();
|
||||
void scrollTo(int target);
|
||||
void createFonts();
|
||||
void destroyFonts();
|
||||
void destroyTextures();
|
||||
|
||||
// Search mode. Activates on the first typed character and filters the
|
||||
// flat proclamation pool (title + content) with word-prefix matching.
|
||||
void enterSearchMode();
|
||||
void exitSearchMode();
|
||||
void rebuildSearchResults();
|
||||
void appendSearchText(const char* utf8);
|
||||
bool searchActive() const { return searchActive_; }
|
||||
int activeListSize() const;
|
||||
|
||||
AppState* state_ = nullptr;
|
||||
std::vector<radiantwave::db::ProclamationRecord> proclamations_;
|
||||
std::vector<radiantwave::db::ProclamationCategoryRecord> categories_;
|
||||
std::vector<FlatItem> items_;
|
||||
std::vector<size_t> visible_; // indices into items_, in display order
|
||||
std::vector<size_t> searchResults_; // indices into proclamations_, search mode
|
||||
std::vector<std::string> searchPool_; // lowercase title + content per proclamation
|
||||
int highlightIndex_ = 0; // index into the active list
|
||||
int scrollOffset_ = 0;
|
||||
int visibleCount_ = 8; // rows that fit on screen (recomputed each frame)
|
||||
std::string statusMessage_;
|
||||
|
||||
bool searchActive_ = false;
|
||||
std::string searchQuery_;
|
||||
|
||||
int subscriptionLevelId_ = 1; // stored license level; 1 (Basic) without one
|
||||
int flashItemIndex_ = -1; // items_ index flashing red (locked attempt)
|
||||
uint64_t flashUntilMs_ = 0; // SDL_GetTicks() deadline for the flash
|
||||
|
||||
TTF_Font* fontTitle_ = nullptr;
|
||||
TTF_Font* fontItem_ = nullptr;
|
||||
TTF_Font* fontSmall_ = nullptr;
|
||||
|
||||
CachedText titleText_;
|
||||
CachedText statusText_;
|
||||
CachedText searchText_;
|
||||
CachedText emptyHintText_;
|
||||
CachedText footerText_;
|
||||
std::vector<CachedText> rowTexts_;
|
||||
std::vector<CachedText> searchRowTexts_; // indexed by proclamations_ id
|
||||
};
|
||||
Reference in New Issue
Block a user