GroveEngine/include/grove/IUI_Enums.h
StillHammer fad105afb2 feat: Implement complete IDataNode/IDataTree system with JSON backend
Major feature: Unified config/data/runtime tree system

**New System Architecture:**
- Unified data tree for config, persistent data, and runtime state
- Three separate roots: config/ (read-only + hot-reload), data/ (read-write + save), runtime/ (temporary)
- Support for modding, saves, and hot-reload in single system

**Interfaces:**
- IDataValue: Abstract data value interface (type-safe access)
- IDataNode: Tree node with navigation, search, and modification
- IDataTree: Root container with config/data/runtime management

**Concrete Implementations:**
- JsonDataValue: nlohmann::json backed value
- JsonDataNode: Full tree navigation with pattern matching & queries
- JsonDataTree: File-based JSON storage with hot-reload

**Features:**
- Pattern matching search (wildcards support)
- Property-based queries with predicates
- SHA256 hashing for validation/sync
- Hot-reload for config/ directory
- Save operations for data/ persistence
- Read-only enforcement for config/

**API Changes:**
- All namespaces changed from 'warfactory' to 'grove'
- IDataTree: Added getConfigRoot(), getDataRoot(), getRuntimeRoot()
- IDataTree: Added saveData(), saveNode() for persistence
- IDataNode: Added setChild(), removeChild(), clearChildren()
- CMakeLists.txt: Added OpenSSL dependency for hashing

**Usage:**
```cpp
auto tree = DataTreeFactory::create("json", "./gamedata");
auto config = tree->getConfigRoot();     // Read-only game config
auto data = tree->getDataRoot();         // Player saves
auto runtime = tree->getRuntimeRoot();   // Temporary state

// Hot-reload config on file changes
if (tree->reloadIfChanged()) { /* refresh modules */ }

// Save player progress
data->setChild("progress", progressNode);
tree->saveData();
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 15:36:25 +08:00

340 lines
11 KiB
C++

#pragma once
#include <nlohmann/json.hpp>
#include <string>
#include <functional>
namespace grove {
using json = nlohmann::json;
// ========================================
// ENUMS FOR TYPE SAFETY
// ========================================
/**
* @brief Data types for UI display
*/
enum class DataType {
ECONOMY,
MAP,
INVENTORY,
CONSOLE,
PERFORMANCE,
COMPANIES,
ALERTS,
PRODUCTION,
LOGISTICS,
PLAYER,
SETTINGS,
DEBUG,
CUSTOM // For extending with string fallback
};
/**
* @brief Request types from UI
*/
enum class RequestType {
GET_PRICES,
GET_CHUNK,
MOVE_PLAYER,
SAVE_GAME,
LOAD_GAME,
CLOSE_WINDOW,
FOCUS_WINDOW,
UPDATE_SETTINGS,
EXECUTE_COMMAND,
CUSTOM // For extending with string fallback
};
/**
* @brief Event/message levels
*/
enum class EventLevel {
INFO,
SUCCESS,
WARNING,
ERROR,
DEBUG,
TRACE
};
/**
* @brief Dock types for window management
*/
enum class DockType {
DOCK, // Standard dockable panel
SPLIT, // Horizontal/vertical split
TABBED, // Tabbed container
FLOATING // Floating window
};
/**
* @brief Dock positions
*/
enum class DockPosition {
LEFT,
RIGHT,
TOP,
BOTTOM,
CENTER,
TAB // Add as tab to parent
};
/**
* @brief Split orientations
*/
enum class Orientation {
HORIZONTAL,
VERTICAL
};
/**
* @brief Pure Generic UI Interface - Type-safe with enums
*/
class IUI {
public:
virtual ~IUI() = default;
// ========================================
// LIFECYCLE
// ========================================
virtual void initialize(const json& config) = 0;
virtual bool update() = 0;
virtual void shutdown() = 0;
// ========================================
// GENERIC DATA FLOW - ENUM VERSIONS
// ========================================
/**
* @brief Display data with type-safe enum
* @param dataType Enum data type
* @param data JSON with content + optional window config:
* {
* "content": {...}, // Actual data to display
* "window": { // Window configuration (optional)
* "id": "window_id",
* "title": "Window Title",
* "parent": "parent_dock_id",
* "dock": "left|right|top|bottom|center|tab",
*
* // SIZE SYSTEM - Hybrid percentage + absolute constraints
* "size": {"width": "20%", "height": 300}, // Target: 20% of parent width, 300px height
* "size": {"width": 400, "height": "50%"}, // Target: 400px width, 50% of parent height
* "size": {"width": "30%", "height": "40%"}, // Target: 30% width, 40% height
*
* "min_size": {"width": 200, "height": 150}, // ABSOLUTE minimum in pixels (always respected)
* "max_size": {"width": 800, "height": "80%"}, // Maximum: 800px width OR 80% of parent (whichever smaller)
*
* "position": {"x": 100, "y": 50},
* "floating": false,
* "resizable": true,
* "closeable": true,
* "collapsible": false
* }
* }
*/
virtual void showData(DataType dataType, const json& data) = 0;
/**
* @brief Display custom data type (fallback to string)
* @param customType Custom data type name
* @param data JSON data
*/
virtual void showDataCustom(const std::string& customType, const json& data) = 0;
/**
* @brief Handle user request with type-safe enum
* @param requestType Enum request type
* @param callback Function to call when request happens
*/
virtual void onRequest(RequestType requestType, std::function<void(const json&)> callback) = 0;
/**
* @brief Handle custom request type (fallback to string)
* @param customType Custom request type name
* @param callback Function to call when request happens
*/
virtual void onRequestCustom(const std::string& customType, std::function<void(const json&)> callback) = 0;
/**
* @brief Show event with type-safe level
* @param level Event level enum
* @param message Human readable text
*/
virtual void showEvent(EventLevel level, const std::string& message) = 0;
// ========================================
// WINDOW MANAGEMENT - ENUM VERSIONS
// ========================================
/**
* @brief Create dock with type-safe enums
* @param dockId Unique dock identifier
* @param type Dock type enum
* @param position Dock position enum
* @param config Additional configuration:
* {
* "parent": "parent_dock_id", // Parent dock (optional)
*
* // HYBRID SIZE SYSTEM
* "size": {"width": "25%", "height": 200}, // Target: 25% of parent width, 200px height
* "min_size": {"width": 200, "height": 100}, // ABSOLUTE minimum pixels (overrides percentage)
* "max_size": {"width": "50%", "height": 600}, // Maximum: 50% of parent OR 600px (whichever smaller)
*
* "orientation": "horizontal", // For SPLIT type
* "collapsible": true, // Can be collapsed
* "resizable": true, // Can be resized
* "tabs": true // Enable tabbed interface
* }
*/
virtual void createDock(const std::string& dockId, DockType type, DockPosition position, const json& config = {}) = 0;
/**
* @brief Create split dock with orientation
* @param dockId Unique dock identifier
* @param orientation Split orientation
* @param config Additional configuration:
* {
* "parent": "parent_dock_id", // Parent dock (optional)
* "size": {"width": 300, "height": 200}, // Initial size
* "min_size": {"width": 100, "height": 50}, // Minimum split size in pixels
* "max_size": {"width": 1000, "height": 800}, // Maximum split size in pixels
* "split_ratio": 0.5, // Split ratio (0.0 to 1.0)
* "min_panel_size": 80, // Minimum size for each panel in split
* "resizable": true // Can be resized by dragging splitter
* }
*/
virtual void createSplit(const std::string& dockId, Orientation orientation, const json& config = {}) = 0;
/**
* @brief Close window or dock
* @param windowId Window/dock ID to close
*/
virtual void closeWindow(const std::string& windowId) = 0;
/**
* @brief Focus window
* @param windowId Window ID to focus
*/
virtual void focusWindow(const std::string& windowId) = 0;
// ========================================
// GENERIC STATE
// ========================================
virtual json getState() const = 0;
virtual void setState(const json& state) = 0;
// ========================================
// CONVENIENCE METHODS WITH ENUMS
// ========================================
void info(const std::string& message) {
showEvent(EventLevel::INFO, message);
}
void success(const std::string& message) {
showEvent(EventLevel::SUCCESS, message);
}
void warning(const std::string& message) {
showEvent(EventLevel::WARNING, message);
}
void error(const std::string& message) {
showEvent(EventLevel::ERROR, message);
}
void debug(const std::string& message) {
showEvent(EventLevel::DEBUG, message);
}
};
// ========================================
// ENUM TO STRING CONVERSIONS (for implementations)
// ========================================
/**
* @brief Convert DataType enum to string (for implementations that need strings)
*/
constexpr const char* toString(DataType type) {
switch (type) {
case DataType::ECONOMY: return "economy";
case DataType::MAP: return "map";
case DataType::INVENTORY: return "inventory";
case DataType::CONSOLE: return "console";
case DataType::PERFORMANCE: return "performance";
case DataType::COMPANIES: return "companies";
case DataType::ALERTS: return "alerts";
case DataType::PRODUCTION: return "production";
case DataType::LOGISTICS: return "logistics";
case DataType::PLAYER: return "player";
case DataType::SETTINGS: return "settings";
case DataType::DEBUG: return "debug";
case DataType::CUSTOM: return "custom";
default: return "unknown";
}
}
constexpr const char* toString(RequestType type) {
switch (type) {
case RequestType::GET_PRICES: return "get_prices";
case RequestType::GET_CHUNK: return "get_chunk";
case RequestType::MOVE_PLAYER: return "move_player";
case RequestType::SAVE_GAME: return "save_game";
case RequestType::LOAD_GAME: return "load_game";
case RequestType::CLOSE_WINDOW: return "close_window";
case RequestType::FOCUS_WINDOW: return "focus_window";
case RequestType::UPDATE_SETTINGS: return "update_settings";
case RequestType::EXECUTE_COMMAND: return "execute_command";
case RequestType::CUSTOM: return "custom";
default: return "unknown";
}
}
constexpr const char* toString(EventLevel level) {
switch (level) {
case EventLevel::INFO: return "info";
case EventLevel::SUCCESS: return "success";
case EventLevel::WARNING: return "warning";
case EventLevel::ERROR: return "error";
case EventLevel::DEBUG: return "debug";
case EventLevel::TRACE: return "trace";
default: return "unknown";
}
}
constexpr const char* toString(DockType type) {
switch (type) {
case DockType::DOCK: return "dock";
case DockType::SPLIT: return "split";
case DockType::TABBED: return "tabbed";
case DockType::FLOATING: return "floating";
default: return "unknown";
}
}
constexpr const char* toString(DockPosition pos) {
switch (pos) {
case DockPosition::LEFT: return "left";
case DockPosition::RIGHT: return "right";
case DockPosition::TOP: return "top";
case DockPosition::BOTTOM: return "bottom";
case DockPosition::CENTER: return "center";
case DockPosition::TAB: return "tab";
default: return "unknown";
}
}
constexpr const char* toString(Orientation orient) {
switch (orient) {
case Orientation::HORIZONTAL: return "horizontal";
case Orientation::VERTICAL: return "vertical";
default: return "unknown";
}
}
} // namespace grove