extern crate self as yog_kit;
pub mod bind;
mod host;
pub mod items;
mod screen;
pub mod testing;
pub use host::{Update, Viewport};
pub use screen::{handle_of, Cx, Screen, ScreenHandle};
pub use yog_api::ui::{Action, StateFlags, Widget};
pub mod prelude {
pub use crate::{Cx, ScreenHandle, ViewModel};
}
#[allow(unused_variables)]
pub trait ViewModel: Send + 'static {
fn on_open(&mut self, cx: &mut Cx<'_, Self>)
where
Self: Sized,
{
}
fn on_close(&mut self, cx: &mut Cx<'_, Self>)
where
Self: Sized,
{
}
fn on_back(&mut self, cx: &mut Cx<'_, Self>) -> bool
where
Self: Sized,
{
false
}
fn customize(&self, root: &mut Widget) {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Anchor {
#[default]
Center,
TopLeft,
Top,
TopRight,
Left,
Right,
BottomLeft,
Bottom,
BottomRight,
Fill,
}
impl Anchor {
pub fn place(self, sw: f32, sh: f32, w: f32, h: f32) -> (f32, f32) {
let cx = ((sw - w) / 2.0).floor();
let cy = ((sh - h) / 2.0).floor();
let (x, y) = match self {
Anchor::Center => (cx, cy),
Anchor::TopLeft | Anchor::Fill => (0.0, 0.0),
Anchor::Top => (cx, 0.0),
Anchor::TopRight => (sw - w, 0.0),
Anchor::Left => (0.0, cy),
Anchor::Right => (sw - w, cy),
Anchor::BottomLeft => (0.0, sh - h),
Anchor::Bottom => (cx, sh - h),
Anchor::BottomRight => (sw - w, sh - h),
};
(x.max(0.0), y.max(0.0))
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ScreenMeta {
pub id: &'static str,
pub w: f32,
pub h: f32,
pub anchor: Anchor,
pub modal: bool,
pub pause: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ViewEvent {
Action(Action),
TextChanged { slot: u16, text: String },
TextSubmitted { slot: u16, text: String },
Select { list: u16, index: u32 },
}
pub trait View: Sized + Send + 'static {
type Vm: ViewModel;
const META: ScreenMeta;
fn build() -> (Self, Widget, Parts);
fn update(&mut self, root: &mut Widget, vm: &Self::Vm, u: &mut Update);
fn dispatch(&mut self, vm: &mut Self::Vm, cx: &mut Cx<'_, Self::Vm>, ev: ViewEvent);
}
#[derive(Debug, Clone)]
pub struct ScrollerPart {
pub path: Vec<u16>,
pub state: yog_api::ui::ScrollState,
}
#[derive(Debug, Clone)]
pub struct TextBoxPart {
pub path: Vec<u16>,
pub state: yog_api::ui::TextBoxState,
}
#[derive(Debug, Clone)]
pub struct ListPart {
pub owner: u16,
pub path: Vec<u16>,
pub scroller: Option<u16>,
pub item_height: Option<f32>,
pub len: u32,
pub selected: Option<u32>,
}
#[derive(Debug, Clone, Default)]
pub struct Parts {
pub scrollers: Vec<ScrollerPart>,
pub text_boxes: Vec<TextBoxPart>,
pub lists: Vec<ListPart>,
pub focusables: Vec<Vec<u16>>,
}
impl Parts {
pub fn new() -> Self {
Self::default()
}
pub fn scroller(&mut self, path: &[u16]) -> u16 {
self.scrollers.push(ScrollerPart {
path: path.to_vec(),
state: Default::default(),
});
(self.scrollers.len() - 1) as u16
}
pub fn text_box(&mut self, path: &[u16]) -> u16 {
self.text_boxes.push(TextBoxPart {
path: path.to_vec(),
state: Default::default(),
});
self.focusables.push(path.to_vec());
(self.text_boxes.len() - 1) as u16
}
pub fn list(&mut self, owner: u16, path: &[u16], scroller: Option<u16>, item_height: Option<f32>) {
self.lists.push(ListPart {
owner,
path: path.to_vec(),
scroller,
item_height,
len: 0,
selected: None,
});
if scroller.is_some() {
self.focusables.push(path.to_vec());
}
}
pub fn focusable(&mut self, path: &[u16]) {
self.focusables.push(path.to_vec());
}
}
#[doc(hidden)]
pub mod __codegen {
pub const CODEGEN: u32 = 1;
pub const fn require(version: u32) {
if version > CODEGEN {
panic!("this .yui code was generated for a newer yog-kit; update the yog-kit dependency");
}
if version < 1 {
panic!("this .yui code was generated by an old yog; regenerate it with `yog build`");
}
}
}