diff --git a/.gitignore b/.gitignore index 796b96d..6864b67 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ /build +/.idea +/.vs +/build +/build_test +/cmake-build* +/out diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..cc24155 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,73 @@ +# Mosis Designer Agent Guidelines + +## Build, Lint, and Test Commands + +### Build Commands +- `cmake --build build --config Debug` - Build the project in debug mode +- `cmake --build build --config Release` - Build the project in release mode +- `cmake -B build` - Configure the build system +- `cmake --build build --parallel 4` - Build with 4 parallel jobs + +### Lint Commands +- No specific linting tools configured +- Uses C++23 standard with clang-tidy if available + +### Test Commands +- No unit tests configured +- Manual testing required for functionality verification + +## Code Style Guidelines + +### General +- Follow C++23 standard with modern C++ features +- Use snake_case for variable and function names +- Use camelCase for class and struct names +- Use uppercase for constants and enum values + +### Naming Conventions +- Functions: camelCase +- Variables: snake_case +- Classes/Structs: camelCase +- Constants: UPPER_CASE +- Enums: UPPER_CASE with prefix (e.g., `enum class FileType { XML, RML };`) + +### Includes and Imports +- Use angle brackets for system headers: `#include ` +- Use quotes for local headers: `#include "header.h"` +- Group includes: system headers, then local headers +- Sort includes alphabetically within groups + +### Formatting +- 4 spaces for indentation (no tabs) +- No trailing whitespace +- Unix line endings (\n) +- One statement per line +- Function definitions: space after function name, no space before opening parenthesis +- If statements: space after keyword, no space before opening parenthesis + +### Error Handling +- Use exceptions for error conditions +- Check return values of system calls +- Prefer early returns over nested conditionals +- Use constexpr for compile-time constants + +### Memory Management +- Prefer stack allocation over heap +- Use smart pointers (std::unique_ptr, std::shared_ptr) +- Avoid raw pointers when possible +- Use RAII principles + +### Documentation +- Document public APIs with comments +- Use Doxygen-style comments for functions and classes +- Keep comments concise and clear + +## Special Rules + +### Cursor Rules +- No cursor rules configured +- No .cursorrules file found + +### Copilot Rules +- No copilot instructions configured +- No .github/copilot-instructions.md file found \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..bafa9f6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,55 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Mosis Designer is a Windows desktop application for previewing RML/RCSS files using the RmlUi library. It provides live reloading when files change in the assets directory. + +## Build Commands + +```bash +# Configure the build (requires vcpkg for glfw3 and freetype) +cmake -B build + +# Build debug +cmake --build build --config Debug + +# Build release +cmake --build build --config Release + +# Build with parallel jobs +cmake --build build --parallel 4 +``` + +## Running the Application + +```bash +# Run with an RML file +./build/Debug/mosis-designer.exe assets/demo.rml +``` + +The application watches the parent directory of the loaded file for changes and automatically reloads. + +## Architecture + +Single-file C++23 application (`main.cpp`) that: +- Uses RmlUi for rendering HTML/CSS-like markup (RML/RCSS) +- Uses GLFW + OpenGL 3 backend from RmlUi +- Windows-specific file watching via `FindFirstChangeNotification` +- Automatically loads all `.ttf` fonts from the RML file's directory + +## Dependencies + +- **RmlUi**: Fetched via CMake FetchContent from GitHub +- **GLFW3**: Via vcpkg +- **FreeType**: Via vcpkg + +## Code Style + +- C++23 standard +- 4 spaces indentation +- snake_case for variables, camelCase for functions/classes +- UPPER_CASE for constants and enums +- Early returns preferred over nested conditionals +- Smart pointers over raw pointers diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b90b5b..b79f195 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,20 +4,36 @@ project("mosis-designer") set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) -find_package(RmlUi CONFIG REQUIRED) -find_package(glfw3 CONFIG REQUIRED) +# Use FetchContent for RmlUi +include(FetchContent) -set(RMLUI_BACKEND "D:/vcpkg/buildtrees/rmlui/src/6.1-fbf6dfc3b5.clean/Backends") +# Fetch RmlUi from GitHub +FetchContent_Declare( + rmlui + GIT_REPOSITORY https://github.com/mikke89/RmlUi.git + GIT_TAG master +) + +FetchContent_MakeAvailable(rmlui) + +# Find other dependencies via vcpkg +find_package(glfw3 CONFIG REQUIRED) +find_package(freetype CONFIG REQUIRED) + +# Get the RmlUi source directory for include paths +FetchContent_GetProperties(rmlui) +set(RMLUI_SOURCE_DIR ${rmlui_SOURCE_DIR}) add_executable(mosis-designer main.cpp - ${RMLUI_BACKEND}/RmlUi_Backend_GLFW_GL3.cpp - ${RMLUI_BACKEND}/RmlUi_Platform_GLFW.cpp - ${RMLUI_BACKEND}/RmlUi_Renderer_GL3.cpp + ${rmlui_SOURCE_DIR}/Backends/RmlUi_Backend_GLFW_GL3.cpp + ${rmlui_SOURCE_DIR}/Backends/RmlUi_Platform_GLFW.cpp + ${rmlui_SOURCE_DIR}/Backends/RmlUi_Renderer_GL3.cpp ) target_link_libraries(mosis-designer PUBLIC - RmlUi::RmlUi glfw + RmlUi::RmlUi glfw freetype ) target_include_directories(mosis-designer PUBLIC - ${RMLUI_BACKEND} -) + ${RMLUI_SOURCE_DIR} + ${RMLUI_SOURCE_DIR}/Backends +) \ No newline at end of file diff --git a/assets/demo.rml b/assets/demo.rml index 5af0f3e..4879b46 100644 --- a/assets/demo.rml +++ b/assets/demo.rml @@ -1,28 +1,35 @@ - + + Fullscreen Mobile UI - - + +
- 22:47 -
- 📶 - 🔋 -
+ 22:47 +
+ 📶 + 🔋 + 📶 + 🔋 + 📶 + 🔋 +
-
-

Activity

-

Monday, January 5

-
+
+

Hello omar 3 hello! and hello LEO 2 Hello!

+
- -
\ No newline at end of file + + diff --git a/assets/html.rcss b/assets/html.rcss new file mode 100644 index 0000000..ac19961 --- /dev/null +++ b/assets/html.rcss @@ -0,0 +1,93 @@ +body, div, +h1, h2, h3, h4, +h5, h6, p, +hr, pre, +tabset tabs +{ + display: block; +} + +h1 +{ + font-size: 2em; + margin: .67em 0; +} + +h2 +{ + font-size: 1.5em; + margin: .75em 0; +} + +h3 +{ + font-size: 1.17em; + margin: .83em 0; +} + +h4, p +{ + margin: 1.12em 0; +} + +h5 +{ + font-size: .83em; + margin: 1.5em 0; +} + +h6 +{ + font-size: .75em; + margin: 1.67em 0; +} + +h1, h2, h3, h4, +h5, h6, strong +{ + font-weight: bold; +} + +em +{ + font-style: italic; +} + +pre +{ + white-space: pre; +} + +hr +{ + border-width: 1px; +} + +table +{ + box-sizing: border-box; + display: table; +} +tr +{ + box-sizing: border-box; + display: table-row; +} +td +{ + box-sizing: border-box; + display: table-cell; +} +col +{ + box-sizing: border-box; + display: table-column; +} +colgroup +{ + display: table-column-group; +} +thead, tbody, tfoot +{ + display: table-row-group; +} diff --git a/assets/phone.rcss b/assets/phone.rcss index 007f4f0..ac5a740 100644 --- a/assets/phone.rcss +++ b/assets/phone.rcss @@ -12,19 +12,20 @@ body { /* Status Bar pinned to top */ #status-bar { display: block; - height: 40px; + height: 140px; padding: 10px 20px 0; - background-color: rgba(0, 0, 0, 0.2); + background-color: rgba(255, 0, 0, 0.2); } .time { float: left; font-weight: bold; - font-size: 1.1em; + font-size: 2em; } .status-icons { float: right; + font-size: 2em; } .icon { @@ -94,8 +95,16 @@ h1 { .nav-item { font-size: 1.9em; color: #888; + background-color: red; + width: 100px; + height: 100px; + text-align: center; + vertical-align: middle; + line-height: 90px; + border-radius: 10px; } .nav-item:hover { color: #3498db; + background-color: blue; } \ No newline at end of file diff --git a/main.cpp b/main.cpp index 4d11ac9..4129840 100644 --- a/main.cpp +++ b/main.cpp @@ -2,39 +2,44 @@ #include #include #include +#include #include #include #include #include -void load_fonts() +void load_fonts(const std::filesystem::path& dir) { - const Rml::String directory = "assets/"; - - struct FontFace { - const char* filename; - bool fallback_face; - }; - FontFace font_faces[] = { - {"LatoLatin-Regular.ttf", false}, - {"LatoLatin-Italic.ttf", false}, - {"LatoLatin-Bold.ttf", false}, - {"LatoLatin-BoldItalic.ttf", false}, - {"NotoEmoji-Regular.ttf", true}, - }; - - for (const FontFace& face : font_faces) - Rml::LoadFontFace(directory + face.filename, face.fallback_face); + for (const auto& file : std::filesystem::directory_iterator(dir)) + { + if (file.path().extension() == ".ttf") + { + Rml::LoadFontFace(file.path().string()); + } + } } -int main() +int main(const int argc, const char* argv[]) { - const int window_width = 1024; - const int window_height = 768; + constexpr int window_width = 540; + constexpr int window_height = 960; + + if (argc < 2) + { + std::println("Usage: mosis-designer file.rml"); + return EXIT_FAILURE; + } + + const std::filesystem::path file = argv[1]; + if (!std::filesystem::exists(file)) + { + std::println("File does not exist"); + return EXIT_FAILURE; + } if (!Backend::Initialize("Load Document Sample", window_width, window_height, true)) { - return -1; + return EXIT_FAILURE; } Rml::SetSystemInterface(Backend::GetSystemInterface()); @@ -46,21 +51,19 @@ int main() { Rml::Shutdown(); Backend::Shutdown(); - return -1; + return EXIT_FAILURE; } - load_fonts(); + const std::filesystem::path assets_path = std::filesystem::absolute(file.parent_path()); + load_fonts(assets_path); - Rml::ElementDocument* document = context->LoadDocument("assets/demo.rml"); + Rml::ElementDocument* document = context->LoadDocument(file.string()); if (document) { document->Show(); } - const std::wstring assets_path = std::filesystem::absolute( - std::filesystem::current_path() / "assets").wstring(); - - HANDLE hNotif = FindFirstChangeNotification(assets_path.c_str(), + const HANDLE hNotif = FindFirstChangeNotification(assets_path.c_str(), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE); bool running = true; @@ -73,7 +76,7 @@ int main() context->UnloadDocument(document); context->Update(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - document = context->LoadDocument("assets/demo.rml"); + document = context->LoadDocument(file.string()); if (document) { document->ReloadStyleSheet();