View Conversion API

This page documents the public APIs in flor::view related to view identity, generic view objects, and child-view sequences. For usage-oriented guidance, see Framework DSL.

Imports

use flor::view::{
    IntoView, IntoViewIter, View, ViewBox, ViewIdentity,
};
use flor::view::builder::ViewBuilder;

ViewBox

ViewBox is the generic view object commonly used inside the framework and by container APIs:

pub type ViewBox = Box<dyn View + Send + Sync + 'static>;

The view!(...) macro converts a single view into ViewBox, and the views![...] macro generates Vec<ViewBox>.

ViewIdentity

ViewIdentity is the abstraction builders use to read view identity:

pub trait ViewIdentity {
    fn identity(&self) -> ViewId;
}

Currently both View and ViewBox implement ViewIdentity. Therefore builders based on ViewIdentity can be used not only with concrete views, but also with generic view objects and view wrappers whose return type is impl IntoView.

Common builders such as ClassBuilder, LayoutBuilder, EventBuilder, FocusIndexBuilder, DisableBuilder, TransformBuilder, and ZIndexBuilder all use ViewIdentity to locate the target view.

IntoView

IntoView converts a single view into ViewBox:

pub trait IntoView: ViewIdentity + Send + Sync + 'static {
    fn into_view(self) -> ViewBox;
}

Implementations:

TypeBehavior
T: View + Send + Sync + 'staticWraps it as Box<dyn View + Send + Sync + 'static>
ViewBoxReturns it unchanged

IntoView inherits ViewIdentity. If a function returns impl IntoView, the caller can still chain common builders:

use flor::view::IntoView;
use flor::view::builder::{ClassBuilder, EventBuilder};
use flor_lys::button::button;

fn action(text: &'static str) -> impl IntoView {
    button(text).class("px-2")
}

let save = action("Save")
    .class("font-bold")
    .on_click(|| {
        println!("save");
    });

IntoViewIter

IntoViewIter converts a value into an iterator of ViewBox. It is mainly used by container children, window root views, and ViewBuilder::views:

pub trait IntoViewIter {
    type Iter: Iterator<Item = ViewBox>;

    fn into_view_iter(self) -> Self::Iter;
}

Implementations:

TypeBehavior
T: IntoViewConverts into an iterator containing one ViewBox
Vec<ViewBox>Consumes the list directly

This means APIs accepting impl IntoViewIter can accept both a single view and the view list generated by views![...]:

use flor::views;
use flor_lys::button::button;
use flor_lys::div::div;
use flor_lys::label::label;

let single = div(label("Only one child"));

let multiple = div(views![
    label("Title"),
    button("Confirm"),
]);

ViewBuilder

ViewBuilder appends child views to an existing view:

pub trait ViewBuilder {
    fn views(self, views: impl IntoViewIter) -> Self;

    fn push_view(self, view: impl IntoView) -> Self;
}

views(...) accepts a child-view sequence. Because a single view also implements IntoViewIter, it can accept either one view or a views![...] list. push_view(...) appends one child view.

use flor::view::builder::ViewBuilder;
use flor::views;
use flor_lys::button::button;
use flor_lys::div::div;
use flor_lys::label::label;

let panel = div(views![label("Title")])
    .push_view(button("Save"))
    .views(label("Additional note"));

When passing initial children while creating a container, prefer the container constructor or views![...]. ViewBuilder is more suitable after you already have the parent view value.

Macros

MacroReturn ValuePurpose
view!(child)ViewBoxBoxes a single view into a generic view object
views![a, b, c]Vec<ViewBox>Builds a list of multiple child views

The macros call IntoView::into_view(...) internally, so each element must implement IntoView.