guido 0.12.0

A reactive Rust GUI library using wgpu for Wayland layer shell widgets
Documentation
# Pivots

By default, rotation and scale happen about the widget's centre. A pivot moves
that point.

One pivot serves both `rotate` and `scale`, as CSS gives one `transform-origin`
to the whole group. `translate` ignores it: moving a box is the same movement
wherever the pivot sits.

## Setting a Pivot

```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
    .rotate(45.0)
    .pivot(Pivot::TOP_LEFT)
# ;
# }
```

Now the container rotates around its top-left corner instead of its center.

## Built-in Pivots

| Pivot | Position |
|--------|----------|
| `CENTER` | 50%, 50% (default) |
| `TOP_LEFT` | 0%, 0% |
| `TOP_RIGHT` | 100%, 0% |
| `BOTTOM_LEFT` | 0%, 100% |
| `BOTTOM_RIGHT` | 100%, 100% |
| `TOP` | 50%, 0% |
| `BOTTOM` | 50%, 100% |
| `LEFT` | 0%, 50% |
| `RIGHT` | 100%, 50% |

## Visual Examples

### Rotation from Different Origins

```text
CENTER (default):        TOP_LEFT:
    ┌───┐                ┌───┐
    │ ↻ │                ↻
    └───┘

BOTTOM_RIGHT:
                         ┌───┐
                         │   │↻
                         └───┘
```

## Examples

### Rotate from Top-Left

```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
    .width(80.0)
    .height(80.0)
    .background(Color::rgb(0.3, 0.5, 0.8))
    .rotate(30.0)
    .pivot(Pivot::TOP_LEFT)
# ;
# }
```

### Scale from Bottom-Right

```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
    .scale(1.5)
    .pivot(Pivot::BOTTOM_RIGHT)
# ;
# }
```

### Pivot from Top Edge

```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
    .rotate(15.0)
    .pivot(Pivot::TOP)
# ;
# }
```

## Custom Origin

Specify exact percentages:

```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
// 25% from left, 75% from top
Pivot::percent(25.0, 75.0)
# ;
# }
```

Values are percentages of the widget's size:
- `0.0` = left/top edge
- `0.5` = center
- `1.0` = right/bottom edge

## Reactive Origins

Pivots can be reactive:

```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
let origin = create_signal(Pivot::CENTER);

container()
    .rotate(45.0)
    .pivot(origin)
    .on_click(move || {
        // Cycle through origins
        // `Pivot` carries f32 anchors, so its constants are not patterns —
        // compare, do not match.
        let current = origin.get();
        origin.set(if current == Pivot::CENTER {
            Pivot::TOP_LEFT
        } else if current == Pivot::TOP_LEFT {
            Pivot::BOTTOM_RIGHT
        } else {
            Pivot::CENTER
        });
    })
# ;
# }
```

## Complete Example

```rust
# extern crate guido;
# use guido::prelude::*;
fn origin_demo() -> impl Widget {
    container()
        .layout(Flex::row().spacing(40.0))
        .children([
            // Rotate from center (default)
            create_rotating_box(Pivot::CENTER, "Center"),

            // Rotate from top-left
            create_rotating_box(Pivot::TOP_LEFT, "Top-Left"),

            // Rotate from bottom-right
            create_rotating_box(Pivot::BOTTOM_RIGHT, "Bottom-Right"),
        ])
}

fn create_rotating_box(origin: Pivot, label: &'static str) -> Container {
    let rotation = create_signal(0.0f32);

    container()
        .layout(Flex::column().spacing(8.0))
        .children([
            container()
                .width(60.0)
                .height(60.0)
                .background(Color::rgb(0.3, 0.5, 0.8))
                .corners(8.0)
                .rotate(rotation.transition(Transition::new(300.0, TimingFunction::EaseOut)))
                .pivot(origin)
                .when_hovered(|s| s.lighter(0.1))
                .on_click(move || rotation.update(|r| *r += 45.0)),
            container().child(text(label).font_size(12.0).color(Color::WHITE)),
        ])
}
# fn main() {}
```

## API Reference

```rust,ignore
# // not compiled: a signature listing — these declarations have no bodies.
impl Container {
    pub fn pivot(
        self,
        origin: impl IntoSignal<Pivot, M>
    ) -> Self;
}

impl Pivot {
    pub const CENTER: Pivot;
    pub const TOP_LEFT: Pivot;
    pub const TOP_RIGHT: Pivot;
    pub const BOTTOM_LEFT: Pivot;
    pub const BOTTOM_RIGHT: Pivot;
    pub const TOP: Pivot;
    pub const BOTTOM: Pivot;
    pub const LEFT: Pivot;
    pub const RIGHT: Pivot;

    pub fn percent(x_percent: f32, y_percent: f32) -> Pivot;  // 0-100
    pub fn px(x: f32, y: f32) -> Pivot;
}
```