Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions .claude/commands/take-issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,27 @@ description: Implements an issue from the backlog
argument-hint: [issue-id]
---
you will, in this order:

1. use gh cli to read the issue #$1.
2. ensure all issues required before working on this one are resolved.

2.1 if not, suggest the first unresolved dependency issue to be worked on first and stop here.
3. check if the issue has a size label.

1. check if the issue has a size label.

3.1 if not, assess the complexity and add one of the following labels:
* 'size: xs' - Less than half a day
* 'size: s' - Half a day
* 'size: m' - One day
* 'size: l' - Two days (broken into subtasks)
* 'size: xl' - More than two days (broken into subtasks)
4. if the size is 'l' or 'xl', check if the issue is already broken into sub-tasks.
* 'size: xs' - Less than half a day
* 'size: s' - Half a day
* 'size: m' - One day
* 'size: l' - Two days (broken into subtasks)
* 'size: xl' - More than two days (broken into subtasks)
1. if the size is 'l' or 'xl', check if the issue is already broken into sub-tasks.
4.1 if not, break the issue into smaller sub-tasks and create new github issues for each sub-task, linking them to the original issue, advise to work on the first sub-task to be worked on and stop here.
4.2 if yes, check each sub taks has its own github issue.
4.2.1 if not, create the missing github sub task issues and stop here.
4.2.2 if yes, advise to work on the first sub-task to be worked on and stop here.
5. if the size is 'xs', 's' or 'm', create a branch named after the issue's id and title.
6. delegate the implementation to a subagent.
7. iterate with the subagent until the issue's requirements are met.
8. create a pull request for the implementation.

2. if the size is 'xs', 's' or 'm', create a branch named after the issue's id and title.
3. delegate the implementation to a subagent.
4. iterate with the subagent until the issue's requirements are met.
5. create a pull request for the implementation.
15 changes: 15 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[tools]
cmake = "3.28.6"
"github:rvben/rumdl" = "latest"
hk = "1.18.3"
ninja = "1.13.1"
pkl = "0.29.1"
Expand Down Expand Up @@ -145,6 +146,20 @@ run = """
clang-format -i
"""

[tasks.markdown-check]
description = "Check markdown files for linting issues"
depends = ["check-deps"]
run = """
rumdl check
"""

[tasks.markdown-fix]
description = "Auto-fix markdown linting issues"
depends = ["check-deps"]
run = """
rumdl fmt
"""

[tasks.demo]
description = "Build and run the Prong demo application"
depends = ["build-examples"]
Expand Down
23 changes: 23 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
Prong is a modern C++20 UI framework from BombFork designed for high-performance applications. It's header-mostly, uses CRTP (Curiously Recurring Template Pattern) for zero-cost abstractions, and is both renderer-agnostic and window-agnostic.

**Key Design Principles:**

- Header-mostly architecture (minimal implementation files)
- CRTP-based component system for compile-time polymorphism
- Zero dependencies for core functionality
Expand All @@ -16,17 +17,20 @@ Prong is a modern C++20 UI framework from BombFork designed for high-performance
## Build Commands

### Standard Build

```bash
mkdir build && cd build
cmake .. -DPRONG_BUILD_EXAMPLES=ON -DPRONG_BUILD_TESTS=ON
cmake --build .
```

### Build Options

- `PRONG_BUILD_EXAMPLES` - Build example applications (default: ON)
- `PRONG_BUILD_TESTS` - Build unit tests (default: ON)

### Installation

```bash
sudo cmake --install .
```
Expand Down Expand Up @@ -56,6 +60,7 @@ This eliminates virtual function call overhead while maintaining clean abstracti
### Component System

The `Component` class (`include/bombfork/prong/core/component.h`) is the foundation:

- **Parent/child relationships**: Components form a tree structure with automatic ownership via `std::unique_ptr`
- **Event propagation**: Events flow down from parent to children, with children handling first (topmost rendered components get priority)
- **Coordinate systems**: Uses a relative coordinate system with caching - see detailed section below
Expand All @@ -66,6 +71,7 @@ The `Component` class (`include/bombfork/prong/core/component.h`) is the foundat
### Coordinate System

Prong uses a **relative coordinate system** where child positions are always relative to their parent's origin. This design provides several benefits:

- **Intuitive positioning**: Child components don't need to know their parent's position
- **Automatic updates**: Moving a parent automatically moves all children
- **Layout flexibility**: Layout managers work with local coordinates only
Expand Down Expand Up @@ -160,6 +166,7 @@ The `Component::handleEvent()` method automatically converts global screen coord
#### Cache Invalidation

The global coordinate cache is automatically invalidated when:

- A component's position changes via `setPosition()` or `setBounds()`
- A component is added to a new parent
- Cache invalidation automatically cascades to all descendants
Expand All @@ -177,6 +184,7 @@ You should never need to manually invalidate the cache.
### Renderer Abstraction

The `IRenderer` interface (`include/bombfork/prong/rendering/irenderer.h`) provides:

- Frame lifecycle: `beginFrame()`, `endFrame()`, `present()`
- Drawing primitives: `drawRect()`, `drawSprite()`, `drawText()`
- Batching support: `drawSprites()` for efficient multi-sprite rendering
Expand All @@ -187,6 +195,7 @@ All rendering must go through the `IRenderer` interface. Components receive rend
### Event System

Prong uses a **hierarchical event propagation model** where events flow through the component tree:

- **Event handling**: Components override `handleEventSelf()` to respond to events
- **Automatic propagation**: Events propagate from parent to children automatically via `Component::handleEvent()`
- **Hit testing**: Uses `Component::containsEvent()` for positional event checking
Expand All @@ -203,6 +212,7 @@ Components can specify how they respond to parent resize events through resize b
#### Unified Resize Behavior

The `ResizeBehavior` enum provides unified control over both axes:

- `FIXED`: Keep original size and position (default)
- `SCALE`: Scale proportionally with parent
- `FILL`: Fill available parent space
Expand All @@ -215,6 +225,7 @@ component->setResizeBehavior(Component::ResizeBehavior::FILL);
#### Per-Axis Resize Behavior

For more control, use `AxisResizeBehavior` to set independent horizontal and vertical behavior:

- `AxisResizeBehavior::FIXED`: Keep original size on this axis
- `AxisResizeBehavior::SCALE`: Scale proportionally with parent on this axis
- `AxisResizeBehavior::FILL`: Fill available parent space on this axis
Expand All @@ -226,10 +237,12 @@ panel->setAxisResizeBehavior(Component::AxisResizeBehavior::FIXED,
```

**Important**: When using FlexLayout, per-axis behavior is usually preferred:

- For horizontal FlexLayout (ROW): Use `FIXED` or `SCALE` horizontally (let FlexLayout control width), `FILL` vertically
- For vertical FlexLayout (COLUMN): Use `FILL` horizontally, `FIXED` or `SCALE` vertically (let FlexLayout control height)

Example from demo app:

```cpp
// Left panel in horizontal FlexLayout: fixed width (200px), fills height
leftPanel->setAxisResizeBehavior(Component::AxisResizeBehavior::FIXED,
Expand All @@ -243,6 +256,7 @@ centerPanel->setAxisResizeBehavior(Component::AxisResizeBehavior::FILL,
#### Responsive Constraints

Combine resize behavior with constraints for bounded resizing:

```cpp
Component::ResponsiveConstraints constraints;
constraints.minWidth = 200;
Expand All @@ -255,19 +269,22 @@ component->setConstraints(constraints);
### Layout System

Layout managers (`include/bombfork/prong/layout/`) use CRTP and provide:

- **FlexLayout**: Flexbox-inspired with direction, justify, align, gap, and grow/shrink factors
- **GridLayout**: CSS Grid-inspired with rows/columns and gaps
- **DockLayout**: Docking panels (top, bottom, left, right, center fill)
- **StackLayout**: Simple vertical/horizontal stacking
- **FlowLayout**: Automatic wrapping layout

Layout managers implement:

- `measureLayout()`: Calculate required space for components
- `layout()`: Position and size components within available space

### Theming System

Located in `include/bombfork/prong/theming/`:

- **ThemeManager**: Singleton managing global themes, thread-safe
- **Color**: RGBA color with utility methods and named constants

Expand All @@ -276,6 +293,7 @@ Themes use semantic color names.
## Implementation Files

Only these modules require `.cpp` files (all in `src/`):

- `core/coordinate_system.cpp` - World ↔ Screen transformations
- `core/async_callback_queue.cpp` - Thread-safe callback management
- `theming/theme_manager.cpp` - Global theme state
Expand All @@ -285,6 +303,7 @@ All UI components (Button, Panel, ListBox, TextInput, Dialog, Toolbar, Viewport)
## Namespace Structure

All code lives under `bombfork::prong` with subnamespaces:

- `bombfork::prong::core` - Component base classes
- `bombfork::prong::components` - All UI widgets (Button, Panel, ListBox, TextInput, Dialog, Toolbar, Viewport)
- `bombfork::prong::layout` - Layout managers
Expand All @@ -300,10 +319,12 @@ All code lives under `bombfork::prong` with subnamespaces:
The `TextInput` component requires two platform-specific interfaces for full functionality:

**IClipboard** (`include/bombfork/prong/events/iclipboard.h`):

- Provides clipboard access for copy/paste operations
- Must be injected via `textInput->setClipboard(clipboard)`

**IKeyboard** (`include/bombfork/prong/events/ikeyboard.h`):

- Converts platform-specific key codes to Prong's agnostic `Key` enum
- Must be injected via `textInput->setKeyboard(keyboard)`

Expand Down Expand Up @@ -355,6 +376,7 @@ The mock implementations provide simple in-memory storage for testing without re
## C++20 Features

The codebase requires C++20 and uses:

- Concepts for template constraints
- Ranges for algorithms
- Three-way comparison operator (spaceship)
Expand All @@ -366,6 +388,7 @@ GCC 10+, Clang 13+, or MSVC 2019+ required.
## CMake Integration

When used as a library via FetchContent:

```cmake
FetchContent_Declare(prong
GIT_REPOSITORY https://github.com/bombfork/prong.git
Expand Down
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ mise build
```

This command:

- Configures CMake with Ninja generator
- Builds the core library
- Builds all tests
Expand Down Expand Up @@ -129,6 +130,7 @@ This builds and executes all unit tests. All tests must pass before submitting a
Header dependencies are verified automatically by IWYU and is integrated to cmake and git hooks.

IWYU ensures that:

- Headers only include what they directly use
- No transitive include dependencies
- Header files are self-contained
Expand All @@ -138,6 +140,7 @@ The git hooks will automatically check this before commits.
### Demo Application Testing

The demo app (`examples/demo_app/`) is used for:

- UX testing and validation
- Manual feature testing
- Gathering user feedback
Expand All @@ -160,6 +163,7 @@ Prong follows a **header-only architecture** where possible. Only add `.cpp` imp
- Platform-specific code requiring conditional compilation

**Existing `.cpp` files:**

- `src/core/coordinate_system.cpp` - World ↔ Screen transformations
- `src/core/async_callback_queue.cpp` - Thread-safe callback management
- `src/theming/theme_manager.cpp` - Global theme state
Expand Down Expand Up @@ -193,6 +197,7 @@ class LayoutManager {
Prong uses a **relative coordinate system** where child positions are always relative to their parent:

**DO:**

```cpp
// Position children relative to parent
panel->setPosition(100, 50); // Panel at (100, 50) in parent space
Expand All @@ -201,6 +206,7 @@ panel->addChild(std::move(button)); // Button now at global (120, 60)
```

**DON'T:**

```cpp
// Never use global coordinates when positioning children
int globalX, globalY;
Expand All @@ -209,6 +215,7 @@ button->setPosition(globalX + 20, globalY + 10); // WRONG!
```

**Rendering:**

- Use `getGlobalX()` and `getGlobalY()` in `render()` methods
- Global coordinates are cached automatically
- Never manually track or store global positions
Expand Down Expand Up @@ -376,6 +383,7 @@ mise demo
### 4. Commit

Git hooks will automatically:

- Run clang-format on changed files
- Run iwyu checks
- Validate commit message format
Expand Down Expand Up @@ -405,6 +413,7 @@ Then create a Pull Request on GitHub with:
**Title:** Clear, concise description of changes

**Description should include:**

- Summary of changes
- Motivation and context
- Related issue numbers (e.g., "Fixes #123", "Closes #456")
Expand All @@ -413,6 +422,7 @@ Then create a Pull Request on GitHub with:
- Any breaking changes

**Example PR description:**

```markdown
## Summary
Add responsive resize behavior to Panel component to support dynamic layouts.
Expand Down Expand Up @@ -449,6 +459,7 @@ Prong uses [hk](https://github.com/jdx/hk) to manage git hooks. The configuratio
### Pre-commit Hook

The pre-commit hook automatically:

- Runs `clang-format` on all staged C++ files (`**/*.cpp`, `**/*.h`)
- Checks formatting with `mise run format-check`
- Automatically fixes formatting issues with `mise run format` when `fix = true`
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ For detailed information, see [docs/coordinate_system.md](docs/coordinate_system

### Core Components

```
```text
bombfork::prong::
├── core/ # Base component system
│ ├── Scene # Root scene component (entry point for UI hierarchy)
Expand Down Expand Up @@ -315,6 +315,7 @@ void mouseButtonCallback(GLFWwindow* w, int btn, int action, int mods) {
```

**Key Features:**

- Scene is the entry point for all events from the window system
- Events automatically propagate to children with coordinate conversion
- Children rendered last (topmost) receive events first
Expand Down
Loading