# Element API Reference

Complete API documentation for GPUI's low-level Element trait.

## Element Trait Structure

The `Element` trait requires implementing three associated types and five methods:

```rust
pub trait Element: 'static + IntoElement {
    type RequestLayoutState: 'static;
    type PrepaintState: 'static;

    fn id(&self) -> Option<ElementId>;
    fn source_location(&self) -> Option<&'static std::panic::Location<'static>>;
    fn request_layout(
        &mut self,
        global_id: Option<&GlobalElementId>,
        inspector_id: Option<&InspectorElementId>,
        window: &mut Window,
        cx: &mut App,
    ) -> (LayoutId, Self::RequestLayoutState);
    fn prepaint(
        &mut self,
        global_id: Option<&GlobalElementId>,
        inspector_id: Option<&InspectorElementId>,
        bounds: Bounds<Pixels>,
        request_layout: &mut Self::RequestLayoutState,
        window: &mut Window,
        cx: &mut App,
    ) -> Self::PrepaintState;
    fn paint(
        &mut self,
        global_id: Option<&GlobalElementId>,
        inspector_id: Option<&InspectorElementId>,
        bounds: Bounds<Pixels>,
        request_layout: &mut Self::RequestLayoutState,
        prepaint: &mut Self::PrepaintState,
        window: &mut Window,
        cx: &mut App,
    );
}
```

## Associated Types

### RequestLayoutState

Data passed from `request_layout` to `prepaint` and `paint` phases.

**Usage:**
- Store layout calculations (styled text, child layout IDs)
- Cache expensive computations
- Pass child state between phases

**Examples:**
```rust
// Simple: no state needed
type RequestLayoutState = ();

// Single value
type RequestLayoutState = StyledText;

// Multiple values
type RequestLayoutState = (StyledText, Vec<ChildLayout>);

// Complex struct
pub struct MyLayoutState {
    pub styled_text: StyledText,
    pub child_layouts: Vec<(LayoutId, ChildState)>,
    pub computed_bounds: Bounds<Pixels>,
}
type RequestLayoutState = MyLayoutState;
```

### PrepaintState

Data passed from `prepaint` to `paint` phase.

**Usage:**
- Store hitboxes for interaction
- Cache visual bounds
- Store prepaint results

**Examples:**
```rust
// Simple: just a hitbox
type PrepaintState = Hitbox;

// Optional hitbox
type PrepaintState = Option<Hitbox>;

// Multiple values
type PrepaintState = (Hitbox, Vec<Bounds<Pixels>>);

// Complex struct
pub struct MyPaintState {
    pub hitbox: Hitbox,
    pub child_bounds: Vec<Bounds<Pixels>>,
    pub visible_range: Range<usize>,
}
type PrepaintState = MyPaintState;
```

## Methods

### id()

Returns optional unique identifier for debugging and inspection.

```rust
fn id(&self) -> Option<ElementId> {
    Some(self.id.clone())
}

// Or if no ID needed
fn id(&self) -> Option<ElementId> {
    None
}
```

### source_location()

Returns source location for debugging. Usually returns `None` unless debugging is needed.

```rust
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
    None
}
```

### request_layout()

Calculates sizes and positions for the element tree.

**Parameters:**
- `global_id`: Global element identifier (optional)
- `inspector_id`: Inspector element identifier (optional)
- `window`: Mutable window reference
- `cx`: Mutable app context

**Returns:**
- `(LayoutId, Self::RequestLayoutState)`: Layout ID and state for next phases

**Responsibilities:**
1. Calculate child layouts by calling `child.request_layout()`
2. Create own layout using `window.request_layout()`
3. Return layout ID and state to pass to next phases

**Example:**
```rust
fn request_layout(
    &mut self,
    global_id: Option<&GlobalElementId>,
    inspector_id: Option<&InspectorElementId>,
    window: &mut Window,
    cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
    // 1. Calculate child layouts
    let child_layout_id = self.child.request_layout(
        global_id,
        inspector_id,
        window,
        cx
    ).0;

    // 2. Create own layout
    let layout_id = window.request_layout(
        Style {
            size: size(px(200.), px(100.)),
            ..default()
        },
        vec![child_layout_id],
        cx
    );

    // 3. Return layout ID and state
    (layout_id, MyLayoutState { child_layout_id })
}
```

### prepaint()

Prepares for painting by creating hitboxes and computing final bounds.

**Parameters:**
- `global_id`: Global element identifier (optional)
- `inspector_id`: Inspector element identifier (optional)
- `bounds`: Final bounds calculated by layout engine
- `request_layout`: Mutable reference to layout state
- `window`: Mutable window reference
- `cx`: Mutable app context

**Returns:**
- `Self::PrepaintState`: State for paint phase

**Responsibilities:**
1. Compute final child bounds based on layout bounds
2. Call `child.prepaint()` for all children
3. Create hitboxes using `window.insert_hitbox()`
4. Return state for paint phase

**Example:**
```rust
fn prepaint(
    &mut self,
    global_id: Option<&GlobalElementId>,
    inspector_id: Option<&InspectorElementId>,
    bounds: Bounds<Pixels>,
    request_layout: &mut Self::RequestLayoutState,
    window: &mut Window,
    cx: &mut App,
) -> Self::PrepaintState {
    // 1. Compute child bounds
    let child_bounds = bounds; // or calculated subset

    // 2. Prepaint children
    self.child.prepaint(
        global_id,
        inspector_id,
        child_bounds,
        &mut request_layout.child_state,
        window,
        cx
    );

    // 3. Create hitboxes
    let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);

    // 4. Return paint state
    MyPaintState { hitbox }
}
```

### paint()

Renders the element and handles interactions.

**Parameters:**
- `global_id`: Global element identifier (optional)
- `inspector_id`: Inspector element identifier (optional)
- `bounds`: Final bounds for rendering
- `request_layout`: Mutable reference to layout state
- `prepaint`: Mutable reference to prepaint state
- `window`: Mutable window reference
- `cx`: Mutable app context

**Responsibilities:**
1. Paint children first (bottom to top)
2. Paint own content (backgrounds, borders, etc.)
3. Set up interactions (mouse events, cursor styles)

**Example:**
```rust
fn paint(
    &mut self,
    global_id: Option<&GlobalElementId>,
    inspector_id: Option<&InspectorElementId>,
    bounds: Bounds<Pixels>,
    request_layout: &mut Self::RequestLayoutState,
    prepaint: &mut Self::PrepaintState,
    window: &mut Window,
    cx: &mut App,
) {
    // 1. Paint children first
    self.child.paint(
        global_id,
        inspector_id,
        child_bounds,
        &mut request_layout.child_state,
        &mut prepaint.child_paint_state,
        window,
        cx
    );

    // 2. Paint own content
    window.paint_quad(paint_quad(
        bounds,
        Corners::all(px(4.)),
        cx.theme().background,
    ));

    // 3. Set up interactions
    window.on_mouse_event({
        let hitbox = prepaint.hitbox.clone();
        move |event: &MouseDownEvent, phase, window, cx| {
            if hitbox.is_hovered(window) && phase.bubble() {
                // Handle click
                cx.stop_propagation();
            }
        }
    });

    window.set_cursor_style(CursorStyle::PointingHand, &prepaint.hitbox);
}
```

## IntoElement Integration

Elements must also implement `IntoElement` to be used as children:

```rust
impl IntoElement for MyElement {
    type Element = Self;

    fn into_element(self) -> Self::Element {
        self
    }
}
```

This allows your custom element to be used directly in the element tree:

```rust
div()
    .child(MyElement::new()) // Works because of IntoElement
```

## Common Parameters

### Global and Inspector IDs

Both are optional identifiers used for debugging and inspection:
- `global_id`: Unique identifier across entire app
- `inspector_id`: Identifier for dev tools/inspector

Usually passed through to children without modification.

### Window and Context

- `window: &mut Window`: Window-specific operations (painting, hitboxes, events)
- `cx: &mut App`: App-wide operations (spawning tasks, accessing globals)

## Layout System Integration

### window.request_layout()

Creates a layout node with specified style and children:

```rust
let layout_id = window.request_layout(
    Style {
        size: size(px(200.), px(100.)),
        flex: Flex::Column,
        gap: px(8.),
        ..default()
    },
    vec![child1_layout_id, child2_layout_id],
    cx
);
```

### Bounds<Pixels>

Represents rectangular region:

```rust
pub struct Bounds<T> {
    pub origin: Point<T>,
    pub size: Size<T>,
}

// Create bounds
let bounds = Bounds::new(
    point(px(10.), px(20.)),
    size(px(100.), px(50.))
);

// Access properties
bounds.left()    // origin.x
bounds.top()     // origin.y
bounds.right()   // origin.x + size.width
bounds.bottom()  // origin.y + size.height
bounds.center()  // center point
```

## Hitbox System

### Creating Hitboxes

```rust
// Normal hitbox (blocks events)
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);

// Transparent hitbox (passes events through)
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Transparent);
```

### Using Hitboxes

```rust
// Check if hovered
if hitbox.is_hovered(window) {
    // ...
}

// Set cursor style
window.set_cursor_style(CursorStyle::PointingHand, &hitbox);

// Use in event handlers
window.on_mouse_event(move |event, phase, window, cx| {
    if hitbox.is_hovered(window) && phase.bubble() {
        // Handle event
    }
});
```

## Event Handling

### Mouse Events

```rust
// Mouse down
window.on_mouse_event(move |event: &MouseDownEvent, phase, window, cx| {
    if phase.bubble() && bounds.contains(&event.position) {
        // Handle mouse down
        cx.stop_propagation(); // Prevent bubbling
    }
});

// Mouse up
window.on_mouse_event(move |event: &MouseUpEvent, phase, window, cx| {
    // Handle mouse up
});

// Mouse move
window.on_mouse_event(move |event: &MouseMoveEvent, phase, window, cx| {
    // Handle mouse move
});

// Scroll
window.on_mouse_event(move |event: &ScrollWheelEvent, phase, window, cx| {
    // Handle scroll
});
```

### Event Phase

Events go through two phases:
- **Capture**: Top-down (parent → child)
- **Bubble**: Bottom-up (child → parent)

```rust
move |event, phase, window, cx| {
    if phase.capture() {
        // Handle in capture phase
    } else if phase.bubble() {
        // Handle in bubble phase
    }

    cx.stop_propagation(); // Stop event from continuing
}
```

## Cursor Styles

Available cursor styles:

```rust
CursorStyle::Arrow
CursorStyle::IBeam           // Text selection
CursorStyle::PointingHand    // Clickable
CursorStyle::ResizeLeft
CursorStyle::ResizeRight
CursorStyle::ResizeUp
CursorStyle::ResizeDown
CursorStyle::ResizeLeftRight
CursorStyle::ResizeUpDown
CursorStyle::Crosshair
CursorStyle::OperationNotAllowed
```

Usage:

```rust
window.set_cursor_style(CursorStyle::PointingHand, &hitbox);
```
