This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
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.
# Push changes to remote (from home directory)
bash ~/uidefedit-sync.sh push
# Pull changes from remote
bash ~/uidefedit-sync.sh pull
# 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.
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().
| 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) |
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.ANativeActivity callbacks + timerfd on the main ALooper.patchelf --remove-rpath or the .so won't load in the installed app.std::unique_ptr for parent→child control trees; raw pointers for child→parent back-references. Document owns all wireframes/windows.<patterns>, 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).ControlRegistry::resolve_inheritance() flattens inherits chains (topological sort) so each ControlDef has a complete standalone attribute list.AAssetManager + load_buffer() for pugixml. For libxml2 XSD validation, extract schemas to cache directory first (libxml2 needs filesystem paths for <xs:import schemaLocation>).begin_group()/end_group() for drag sequences. Actions: Place, Move, Resize, Delete, PropertyChange.begin_group()/end_group() for single undo step.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.ImGui::TextDisabled("Label:") on a separate line above the widget, with ##hidden_id for the widget label.Properties::render() to look up slot data.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.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.pm install is blocked by SELinux. Always copy to /sdcard/Download/ then termux-open to trigger the system package installer.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).
Sample XML files in test/ for verifying open/save/validate:
test-basic.xml — Abstract controls, 1 wireframe, 1 windowtest-avalonia.xml — Avalonia controls, 2 wireframes, 2 windowstest-webawesome.xml — Web Awesome controls, form layouttest-complex.xml — WinForms, 3 wireframes, 3 windows, 50+ controlstest-invalid.xml — Intentionally invalid for validation error testing