Struct paws::Ui

source · []
pub struct Ui<T: Renderer> { /* private fields */ }
Expand description

UI state. This is what’s used for laying out groups and drawing to the screen.

The group stack

The group stack is what controls positioning at a given moment. Because paws is an immediate-mode GUI library, there is no intermediate state with nodes and what not. Everything is rendered to the screen directly.

However, during rendering, paws has to keep some information around for layouting. After all, that’s what it’s for: laying out rectangles on the screen. The way it maintains this state is through a stack of groups.

Groups are essentially just glorified rectangles with some extra layouting and rendering data. When you push a new group, the its position is placed relative to the previous group, at a vector called the cursor. When you pop this new group off the stack, the cursor of the group above is offset by the size of the group you just popped off. This allows you to cascade elements, flexbox-style, just without the overhead of holding a hundred or so nodes scattered across heap memory. The group stack grows as you nest more and more groups inside of each other, but old groups are not preserved after they’re popped off the stack.

Of course this paradigm makes laying out simple panels quite easy, but elements that need to preserve state may be a bit more challenging to implement. But worry not, structs come to your rescue! If you want to implement a more complex element that needs to preserve some state across frames, create a struct that’ll hold its data:

// let's assume this is our UI type:
use paws::NoRenderer;
type Ui = paws::Ui<NoRenderer>;

struct Slider {
    value: f32,
    min: f32,
    max: f32,
}

Then, implement a method on this struct that’ll render the element onto the screen, and process all incoming input events:

use paws::Layout;

impl Slider {
    // for brevity, we'll assume no input events need to be processed, as that's outside
    // of paws's scope.
    fn process(&mut self, ui: &mut Ui, width: f32) {
        // create a group that'll span a rectangle with the provided width and the parent
        // group's height
        ui.push((width, ui.height()), Layout::Freeform);
        ui.draw(|ui| {
            // ... do all the rendering work here ...
        });
        ui.pop();
    }
}

Then, simply keep a Slider somewhere outside of your event loop, and call process() when you want to place it onto your UI.

let mut ui = Ui::new(NoRenderer);
let mut slider = Slider {
    value: 0.0,
    min: 0.0,
    max: 32.0,
};

// ↓ this is your event loop! usually done by winit, SDL2, or some other library.
'app: loop {
    // don't forget the root group!
    ui.root(window_size, Layout::Vertical);
    // ... other layout stuff goes here ...
    // when time comes, process() the slider:
    slider.process(&mut ui, 256.0);
}

Initialization

Most of the group-related methods described below will panic if there are no groups on the stack, with the exception of Ui::new (obviously), and Ui::root. The latter is used to initialize the UI state so that at least one group is present, but also to make sure that the group stack doesn’t grow to oblivion if the user forgets to pop a group or two. (This isn’t a good excuse for not popping groups, but it’ll at least prevent your program from leaking memory if you really do forget.)

Panicking

All functions that mention the “current group” are guaranteed to panic if there are no groups on the stack. Other groups, such as the “parent group”, which is the group above the current group, may also appear, but are always followed up with a Panicking section that specify the requirements for these groups’ presence.

Rendering

Because there’s usually no use to using a UI library without any actual rendering, the Ui type takes an extra renderer type as a parameter. The methods from this type are available via the Deref and DerefMut traits, except for names that collide with those defined on Ui itself (obviously). The renderer can be retrieved as an immutable reference (for probing and measurements) using Ui::renderer, and as a mutable reference (for doing actual rendering) using Ui::render.

build!

For your convenience while building UIs, a macro is available to make all those pushes and pops get out of your face. See build!’s documentation for more info.

Implementations

Creates a new UI state with the given renderer.

Returns an immutable reference to the renderer.

Returns a mutable reference to the renderer.

Returns the position of the topmost group, in absolute (screen) coordinates.

Sets the absolute position of the topmost group.

Returns the size of the topmost group.

Returns the width of the topmost group.

Returns the height of the topmost group.

Returns the current group’s rectangle. The rectangle’s position is expressed in absolute coordinates.

Returns the root group’s rectangle.

Returns the “remaining size” of the current group. This is measured by subtracting the group’s cursor from its size, effectively giving you the size that remains in the group. In reversed layouts, the cursor is added instead, as it goes into the negative. On the freeform layout, this always returns (0, 0).

Returns the “remaining width” of the current group, as per the convention described in Ui::remaining_size’s documentation.

Returns the “remaining height” of the current group, as per the convention described in Ui::remaining_size’s documentation.

Clears the group stack and pushes the root group onto the stack, with the given size and layout. The root group is the first group that should be pushed onto the stack. It defines the size of the window, and the initial layout to be used.

Note that this root group must not be popped off manually, as it gets popped off every frame anyways, because the stack is cleared upon calling this function.

Pushes a group onto the group stack, with the given size and layout.

Pops a group off the group stack, updating the cursor of the group under it.

Returns the cursor position of the current group.

Sets the cursor position of the current group. This is most useful with freeform layouts.

Offsets the cursor by the given amount.

Pads the current group with some amount of padding.

Aligns the current group in the parent group, with the provided alignment.

Panics

If there are less than two groups (the parent and the subject) on the stack.

Inserts empty space between subgroups, by increasing or decreasing the cursor position by the given amount.

Panics
  • If there are no groups.
  • On freeform layout, as it’s not clear which direction the spacing should be performed in.

Resizes the current group to fit its children. This function considers a few cases:

  • on Freeform layout, it sets the width and height to the cursor,
  • on Horizontal layout, it sets the width to the cursor’s X position,
  • on Vertical layout, it sets the height to the cursor’s Y position.
  • on reversed layouts, it panics, as layouting there works a bit backwards and fitting currently doesn’t work properly. This might get solved in a future release.
Panics
  • If there are no groups.
  • On reversed layouts, as noted above.

Allows one to draw in the current group by translating the renderer’s matrix to the group’s position. The renderer can be obtained inside of the callback by using Ui::render.

Clips drawing to only occur inside of the current group.

Any pixels outside of the group are discarded. Note that to undo the clip, self.render().push() and self.render().pop() must be used.

Draws a rectangle that fills the current group with the given color.

Draws a rounded rectangle that fills the current group, with the given color and corner radius.

Draws a rectangle outline that creates a border around the current group, with the given color and line thickness.

Draws a rounded rectangle outline that creates a border around the current group, with the given color, corner radius, and line thickness.

Returns the current group’s line cap.

Sets the current group’s line cap for rendering lines. The root group’s default line cap is LineCap::Butt.

Draws a line spanning the left side of the current group, with the given color and line thickness.

Draws a line spanning the top side of the current group, with the given color and line thickness.

Draws a line spanning the right side of the current group, with the given color and line thickness.

Draws a line spanning the bottom side of the current group, with the given color and line thickness.

Draws text inside of the current group, with the given color and alignment inside of the group’s rectangle.

Panics

If there are no groups on the stack, or if a font isn’t set.

Trait Implementations

Any Ui instance acts as if it were the underlying renderer. In case any conflicts occur (such as with Ui::text and Renderer::text, Ui::render may be used to specify that the renderer method should be called instead.

The renderer type.

Dereferences the value.

Any mutable Ui instance acts as if it were the underlying renderer. In case any conflicts occur (such as with Ui::text and Renderer::text, Ui::renderer may be used to specify that the renderer method should be called instead.

Mutably dereferences the value.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.