# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview UIDefEdit is a native Android C++ application for visually designing UI layouts conforming to the `ui-layout-def` XML specification (v1.6). It runs as a NativeActivity built with Clang in Termux. A minimal Java wrapper (`DebugActivity extends NativeActivity`) provides the entry point and soft keyboard support. **Status:** All 8 milestones complete. The app is fully functional: create documents, place controls, edit properties, save/load XML, validate against XSD schemas, and package as APK. ## Sync ```bash # Push changes to remote (from home directory) bash ~/uidefedit-sync.sh push # Pull changes from remote bash ~/uidefedit-sync.sh pull ``` ## Build Commands ```bash # Termux prerequisites (libxml2 is built from source, not needed as system pkg) pkg install clang cmake make git patchelf pkg install aapt2 apksigner zipalign d8 javac # Configure (only needed once) cmake -B build -DCMAKE_BUILD_TYPE=Debug # Build cmake --build build -j$(nproc) # Package APK bash android/build-apk.sh # Install (use termux-open, not pm install — SELinux blocks pm) termux-open build/uidef-edit.apk ``` The CMake build uses Termux's native Clang targeting `aarch64-unknown-linux-android24`. No NDK toolchain file needed. The target is a shared library (`add_library(uidef-tool SHARED ...)`). C++17 standard. AndroidManifest uses `targetSdkVersion=34` (required for modern Android installs). An `android.jar` (API 28+) is required at `$HOME/android.jar` for APK resource linking. ## Architecture ``` ANativeActivity_onCreate (main.cpp) │ Direct callbacks on main UI thread (no android_native_app_glue) │ timerfd + ALooper for ~60fps rendering │ EGL/GLES3 context │ Multi-touch: pinch zoom, double-tap zoom, three-finger undo │ ├── App (app.cpp — lifecycle, docking layout, frame orchestration) │ ├── UI layer (Dear ImGui, docking branch) │ ├── toolbar — top bar: New/Open/Save/Validate + undo/redo + marquee select toggle │ ├── toolbox — left slide-in: control palette by category │ ├── canvas — central: pan/zoom surface with viewport culling │ ├── Bottom tab area (docked together): │ │ ├── doc_tree — wireframe/window hierarchy with inline action buttons │ │ ├── properties — attribute editor + slot properties (labels above fields) │ │ └── validation_panel — XSD error/warning list │ └── file_dialog — custom /sdcard/ browser (single-tap select + Open button) │ ├── Model layer │ ├── Document — root: version, platform, pattern_includes, wireframes, windows │ ├── ControlRegistry — parsed control definitions with resolved inheritance │ ├── ControlInstance — placed control: id, position, properties, parent/children tree │ ├── WireframeDef — template layout with named SlotDefs │ └── WindowDef — wireframe-based (slot overrides) or standalone (template) │ ├── XML engine │ ├── xml_reader/writer — pugixml DOM (round-trips non-visual sections verbatim) │ └── xsd_validator — libxml2 (statically linked, built from source) │ └── Utilities ├── undo_redo — command pattern stack (100 action cap, drag grouping) └── platform — AAssetManager helpers, path resolution ``` **Rendering:** OpenGL ES 3.0 via EGL. ImGui draws all UI. Controls render as color-coded rounded rectangles (blue=input, green=display, gray=container, orange=list). Viewport culling skips off-screen controls. **Portrait orientation** is locked. Toolbox is a left slide-in drawer; Properties, Document Tree, and Validation are docked as tabs in a bottom panel area. Canvas gets maximum vertical space. UI scale derived from screen width (`width / 540dp`). **Dual font system:** Main font (21sp scaled) for toolbar/buttons/headers. Smaller content font (15sp scaled, `Fonts[1]`) for bottom panel content text. Access via `io.Fonts->Fonts[1]` and `ImGui::PushFont()`/`PopFont()`. ## Key Libraries | Library | Purpose | Integration | |---------|---------|-------------| | Dear ImGui (docking branch) | All UI rendering | Source in `third_party/imgui/`, backends: `imgui_impl_android` + `imgui_impl_opengl3` | | pugixml 1.14+ | XML read/write, DOM manipulation | Source in `third_party/pugixml/` (2 files) | | libxml2 2.12.9 | XSD schema validation only | Built from source in `third_party/libxml2/`, statically linked (no ICU/iconv) | ## Critical Patterns - **Static libxml2 without ICU/iconv.** libxml2 2.12.9 is built from source in `third_party/libxml2/` as a static library with heavy dependencies disabled (`LIBXML2_WITH_ICONV=OFF`, `LIBXML2_WITH_ICU=OFF`, `LIBXML2_WITH_LZMA=OFF`, `LIBXML2_WITH_ZLIB=OFF`). This avoids the 32MB+ ICU dependency that Termux's system libxml2 requires. Schema validation (`LIBXML2_WITH_SCHEMAS=ON`) works fully. Added ~1.4MB to APK size. - **No android_native_app_glue.** The NDK's app_glue creates a background pthread that causes ANR with Termux's Clang. Use direct `ANativeActivity` callbacks + `timerfd` on the main `ALooper`. - **RPATH stripping.** Termux's Clang embeds RPATH to its lib dir. The APK build script must strip it with `patchelf --remove-rpath` or the .so won't load in the installed app. - **Ownership:** `std::unique_ptr` for parent→child control trees; raw pointers for child→parent back-references. Document owns all wireframes/windows. - **Round-trip fidelity:** Sections the tool doesn't edit (views, validation-rules, state-management) are preserved as raw pugixml DOM nodes and merged back on save in XSD document order. - **v1.6 XML structure:** Wireframes belong inside ``, not at root. Root element has `xmlns="http://quadarax.com/ui-layout-definition"`. Pattern-includes have `src` and `platform` attributes (`PatternInclude` struct in `document.h`). - **Control inheritance:** `ControlRegistry::resolve_inheritance()` flattens `inherits` chains (topological sort) so each ControlDef has a complete standalone attribute list. - **Asset loading:** APK assets aren't filesystem paths — use `AAssetManager` + `load_buffer()` for pugixml. For libxml2 XSD validation, extract schemas to cache directory first (libxml2 needs filesystem paths for ``). - **Undo/redo:** Per-action with `begin_group()`/`end_group()` for drag sequences. Actions: Place, Move, Resize, Delete, PropertyChange. - **Marquee multi-selection:** Toggle via View > Marquee Select. In select mode, drag on empty canvas draws rectangle to select multiple controls. Group move and group delete supported. Group move uses `begin_group()`/`end_group()` for single undo step. - **Touch-friendly UI:** Resize handles are 12px visual / 28px hit area (`kHandleSize`/`kHandleHitSize` in `selection.h`). Scrollbars are 24dp wide. Doc tree uses inline `[Edit] [Props] [Rename] [Del]` buttons instead of hidden popup menus. Bottom panels have 80px padding to clear Android nav bar. - **Properties labels above fields.** In the narrow bottom tab layout, ImGui widget labels (normally to the right) go off-screen. All property labels use `ImGui::TextDisabled("Label:")` on a separate line above the widget, with `##hidden_id` for the widget label. - **Slot property editing.** When a control marked as a slot is selected in wireframe editing mode, the Properties panel shows a "Slot" section with editable name, allowed controls, required checkbox, and read-only region ID. The active wireframe is passed to `Properties::render()` to look up slot data. - **File dialog single-tap selection.** The file dialog tracks a `selected_index_` for highlighted files. Single-tap highlights a file, enabling the Open button. Double-tap still works as a shortcut to open immediately. Previous behavior (Open button always disabled, double-tap only) was unreliable on touch screens. - **Custom app icon.** Generated by `android/gen_icon.py` (pure Python PNG, no Pillow). Teal rounded square with UI wireframe layout design. 5 density variants (mdpi through xxxhdpi) in `android/res/mipmap-*/ic_launcher.png`. - **Install via termux-open.** Direct `pm install` is blocked by SELinux. Always copy to `/sdcard/Download/` then `termux-open` to trigger the system package installer. ## Control Set Files Bundled in `assets/controls/`: `abstract-controls.xml` (always loaded), `winform-controls.xml`, `avalonia-controls.xml`, `webawesome-controls.xml`. XSD schemas in `assets/schemas/` (8 files). ## Test Documents Sample XML files in `test/` for verifying open/save/validate: - `test-basic.xml` — Abstract controls, 1 wireframe, 1 window - `test-avalonia.xml` — Avalonia controls, 2 wireframes, 2 windows - `test-webawesome.xml` — Web Awesome controls, form layout - `test-complex.xml` — WinForms, 3 wireframes, 3 windows, 50+ controls - `test-invalid.xml` — Intentionally invalid for validation error testing