diff --git a/Cargo.lock b/Cargo.lock index edc4c63..12b55a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1042,16 +1042,36 @@ name = "iris" version = "0.1.0" dependencies = [ "arboard", - "bytemuck", "cosmic-text", - "fxhash", "image", + "iris-core", + "iris-macro", "pollster", "unicode-segmentation", "wgpu", "winit", ] +[[package]] +name = "iris-core" +version = "0.1.0" +dependencies = [ + "bytemuck", + "cosmic-text", + "fxhash", + "image", + "wgpu", + "winit", +] + +[[package]] +name = "iris-macro" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "itertools" version = "0.12.1" @@ -2401,9 +2421,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.110" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index cdf93bf..14186b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,30 @@ [package] name = "iris" -version = "0.1.0" -edition = "2024" default-run = "test" +version.workspace = true +edition.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +iris-core = { workspace = true } +iris-macro = { workspace = true } +cosmic-text = { workspace = true } +unicode-segmentation = { workspace = true } +winit = { workspace = true } +arboard = { workspace = true, features = ["wayland-data-control"] } +pollster = { workspace = true } +wgpu = { workspace = true } +image = { workspace = true } + +[workspace] +members = ["core", "macro"] + +[workspace.package] +version = "0.1.0" +edition = "2024" + +[workspace.dependencies] pollster = "0.4.0" winit = "0.30.12" wgpu = "27.0.1" @@ -15,5 +33,6 @@ image = "0.25.6" cosmic-text = "0.15.0" unicode-segmentation = "1.12.0" fxhash = "0.2.1" -arboard = { version = "3.6.1", features = ["wayland-data-control"] } - +arboard = "3.6.1" +iris-core = { path = "core" } +iris-macro = { path = "macro" } diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 0000000..a85a26d --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "iris-core" +version.workspace = true +edition.workspace = true + +[dependencies] +winit = { workspace = true } +wgpu = { workspace = true } +bytemuck ={ workspace = true } +image = { workspace = true } +cosmic-text = { workspace = true } +fxhash = { workspace = true } diff --git a/src/layout/attr.rs b/core/src/layout/attr.rs similarity index 100% rename from src/layout/attr.rs rename to core/src/layout/attr.rs diff --git a/src/layout/data.rs b/core/src/layout/data.rs similarity index 100% rename from src/layout/data.rs rename to core/src/layout/data.rs diff --git a/src/layout/event.rs b/core/src/layout/event.rs similarity index 64% rename from src/layout/event.rs rename to core/src/layout/event.rs index 4ea16ac..99951ea 100644 --- a/src/layout/event.rs +++ b/core/src/layout/event.rs @@ -1,7 +1,7 @@ use std::{hash::Hash, rc::Rc}; use crate::{ - layout::{IdFnTag, Ui, UiModule, WidgetId, WidgetIdFn, WidgetLike}, + layout::{Ui, UiModule, WeakWidgetId, WidgetId}, util::{HashMap, Id}, }; @@ -18,7 +18,7 @@ pub struct EventCtx<'a, Ctx, Data> { pub type ECtx<'a, Ctx, Data, W> = EventIdCtx<'a, Ctx, Data, W>; pub struct EventIdCtx<'a, Ctx, Data, W> { - pub id: &'a WidgetId, + pub id: &'a WeakWidgetId, pub ui: &'a mut Ui, pub state: &'a mut Ctx, pub data: Data, @@ -30,74 +30,8 @@ impl) + 'static, Ctx, Data> EventFn for F { pub trait WidgetEventFn: Fn(EventIdCtx) + 'static {} impl) + 'static, Ctx, Data, W> WidgetEventFn for F {} -// TODO: naming in here is a bit weird like eventable -#[macro_export] -macro_rules! event_ctx { - ($ty: ty) => { - mod local_event_trait { - use super::*; - #[allow(unused_imports)] - use $crate::prelude::*; - - pub trait EventableCtx { - fn on( - self, - event: E, - f: impl WidgetEventFn, - ) -> impl WidgetIdFn + EventableCtx; - } - - impl, Tag> EventableCtx for WL { - fn on( - self, - event: E, - f: impl WidgetEventFn<$ty, E::Data, WL::Widget>, - ) -> impl WidgetIdFn + EventableCtx { - eventable::Eventable::on(self, event, f) - } - } - } - use local_event_trait::*; - }; -} -pub use event_ctx; - -pub mod eventable { - use super::*; - - pub trait Eventable { - fn on( - self, - event: E, - f: impl WidgetEventFn, - ) -> impl WidgetIdFn + Eventable; - } - - impl, Tag> Eventable for WL { - fn on( - self, - event: E, - f: impl WidgetEventFn, - ) -> impl WidgetIdFn { - move |ui| { - let id = self.add(ui); - let id_ = id.weak(); - ui.register_event(&id, event, move |ctx| { - f(EventIdCtx { - id: &id_.strong(), - state: ctx.state, - data: ctx.data, - ui: ctx.ui, - }); - }); - id - } - } - } -} - pub trait DefaultEvent: Hash + Eq + 'static { - type Data: Clone; + type Data: Clone = (); } impl Event for E { @@ -203,7 +137,7 @@ impl Ui { .data .modules .get_mut::>() - .run(&id.id, event) + .run(&id.id(), event) { f(EventCtx { ui: self, diff --git a/src/layout/mod.rs b/core/src/layout/mod.rs similarity index 57% rename from src/layout/mod.rs rename to core/src/layout/mod.rs index 0e13b5c..cebb4fd 100644 --- a/src/layout/mod.rs +++ b/core/src/layout/mod.rs @@ -1,33 +1,21 @@ -mod color; +mod attr; mod event; -mod id; -mod layer; mod module; mod num; mod orientation; mod painter; -mod text; -mod texture; +mod primitive; mod ui; -mod attr; -mod vec2; mod widget; -mod widgets; -pub use color::*; +pub use attr::*; pub use event::*; -pub use id::*; -pub use layer::*; pub use module::*; pub use num::*; pub use orientation::*; pub use painter::*; -pub use text::*; -pub use texture::*; +pub use primitive::*; pub use ui::*; -pub use attr::*; -pub use vec2::*; pub use widget::*; -pub use widgets::*; pub type UiColor = Color; diff --git a/src/layout/module.rs b/core/src/layout/module.rs similarity index 100% rename from src/layout/module.rs rename to core/src/layout/module.rs diff --git a/core/src/layout/num.rs b/core/src/layout/num.rs new file mode 100644 index 0000000..c4ad5cd --- /dev/null +++ b/core/src/layout/num.rs @@ -0,0 +1,49 @@ +use crate::util::Vec2; +use std::marker::Destruct; + +pub const trait UiNum { + fn to_f32(self) -> f32; +} + +impl const UiNum for f32 { + fn to_f32(self) -> f32 { + self + } +} + +impl const UiNum for u32 { + fn to_f32(self) -> f32 { + self as f32 + } +} + +impl const UiNum for i32 { + fn to_f32(self) -> f32 { + self as f32 + } +} + +pub const fn vec2(x: impl const UiNum, y: impl const UiNum) -> Vec2 { + Vec2::new(x.to_f32(), y.to_f32()) +} + +impl const From for Vec2 { + fn from(v: T) -> Self { + Self { + x: v.to_f32(), + y: v.to_f32(), + } + } +} + +impl const From<(T, U)> for Vec2 +where + (T, U): const Destruct, +{ + fn from((x, y): (T, U)) -> Self { + Self { + x: x.to_f32(), + y: y.to_f32(), + } + } +} diff --git a/src/layout/orientation/align.rs b/core/src/layout/orientation/align.rs similarity index 100% rename from src/layout/orientation/align.rs rename to core/src/layout/orientation/align.rs diff --git a/src/layout/orientation/axis.rs b/core/src/layout/orientation/axis.rs similarity index 100% rename from src/layout/orientation/axis.rs rename to core/src/layout/orientation/axis.rs diff --git a/src/layout/orientation/len.rs b/core/src/layout/orientation/len.rs similarity index 100% rename from src/layout/orientation/len.rs rename to core/src/layout/orientation/len.rs diff --git a/src/layout/orientation/mod.rs b/core/src/layout/orientation/mod.rs similarity index 82% rename from src/layout/orientation/mod.rs rename to core/src/layout/orientation/mod.rs index f6d2963..65040ec 100644 --- a/src/layout/orientation/mod.rs +++ b/core/src/layout/orientation/mod.rs @@ -3,7 +3,7 @@ mod axis; mod len; mod pos; -use super::vec2::*; +use crate::util::Vec2; pub use align::*; pub use axis::*; diff --git a/src/layout/orientation/pos.rs b/core/src/layout/orientation/pos.rs similarity index 100% rename from src/layout/orientation/pos.rs rename to core/src/layout/orientation/pos.rs diff --git a/src/layout/painter.rs b/core/src/layout/painter.rs similarity index 96% rename from src/layout/painter.rs rename to core/src/layout/painter.rs index 8d04ec3..b862ba2 100644 --- a/src/layout/painter.rs +++ b/core/src/layout/painter.rs @@ -1,10 +1,10 @@ use crate::{ layout::{ Axis, Len, Modules, PrimitiveLayers, RenderedText, Size, TextAttrs, TextBuffer, TextData, - TextureHandle, Textures, UiRegion, UiVec2, Vec2, WidgetId, Widgets, + TextureHandle, Textures, UiRegion, UiVec2, WidgetId, Widgets, }, render::{Mask, MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst}, - util::{HashMap, HashSet, Id, TrackedArena}, + util::{HashMap, HashSet, Id, TrackedArena, Vec2}, }; /// makes your surfaces look pretty @@ -33,7 +33,7 @@ struct PainterCtx<'a> { pub modules: &'a mut Modules, pub cache_width: HashMap, pub cache_height: HashMap, - pub needs_redraw: HashSet, + pub needs_redraw: &'a mut HashSet, draw_started: HashSet, } @@ -323,7 +323,7 @@ impl<'a> PainterCtx<'a> { } impl PainterData { - fn ctx(&mut self, needs_redraw: HashSet) -> PainterCtx<'_> { + fn ctx<'a>(&'a mut self, needs_redraw: &'a mut HashSet) -> PainterCtx<'a> { PainterCtx { widgets: &self.widgets, active: &mut self.active, @@ -341,13 +341,14 @@ impl PainterData { } pub fn draw(&mut self, id: Id) { - let mut ctx = self.ctx(Default::default()); + let mut need_redraw = HashSet::default(); + let mut ctx = self.ctx(&mut need_redraw); ctx.draw_started.clear(); ctx.layers.clear(); ctx.draw_inner(0, id, UiRegion::FULL, None, MaskIdx::NONE, None); } - pub fn redraw(&mut self, ids: HashSet) { + pub fn redraw(&mut self, ids: &mut HashSet) { let mut ctx = self.ctx(ids); while let Some(&id) = ctx.needs_redraw.iter().next() { ctx.redraw(id); @@ -399,9 +400,9 @@ impl<'a, 'c> Painter<'a, 'c> { } fn widget_at(&mut self, id: &WidgetId, region: UiRegion) { - self.children.push(id.id); + self.children.push(id.id()); self.ctx - .draw_inner(self.layer, id.id, region, Some(self.id), self.mask, None); + .draw_inner(self.layer, id.id(), region, Some(self.id), self.mask, None); } pub fn texture_within(&mut self, handle: &TextureHandle, region: UiRegion) { @@ -552,11 +553,11 @@ impl SizeCtx<'_> { } pub fn width(&mut self, id: &WidgetId) -> Len { - self.width_inner(id.id) + self.width_inner(id.id()) } pub fn height(&mut self, id: &WidgetId) -> Len { - self.height_inner(id.id) + self.height_inner(id.id()) } pub fn len_axis(&mut self, id: &WidgetId, axis: Axis) -> Len { diff --git a/src/layout/color.rs b/core/src/layout/primitive/color.rs similarity index 100% rename from src/layout/color.rs rename to core/src/layout/primitive/color.rs diff --git a/src/layout/layer.rs b/core/src/layout/primitive/layer.rs similarity index 100% rename from src/layout/layer.rs rename to core/src/layout/primitive/layer.rs diff --git a/core/src/layout/primitive/mod.rs b/core/src/layout/primitive/mod.rs new file mode 100644 index 0000000..8284a05 --- /dev/null +++ b/core/src/layout/primitive/mod.rs @@ -0,0 +1,9 @@ +mod color; +mod layer; +mod text; +mod texture; + +pub use color::*; +pub use layer::*; +pub use text::*; +pub use texture::*; diff --git a/src/layout/text.rs b/core/src/layout/primitive/text.rs similarity index 98% rename from src/layout/text.rs rename to core/src/layout/primitive/text.rs index 169d166..f201f23 100644 --- a/src/layout/text.rs +++ b/core/src/layout/primitive/text.rs @@ -1,11 +1,13 @@ -use std::simd::{Simd, num::SimdUint}; - -use crate::layout::{Align, RegionAlign, TextureHandle, Textures, UiColor, Vec2}; +use crate::{ + layout::{Align, RegionAlign, TextureHandle, Textures, UiColor}, + util::Vec2, +}; use cosmic_text::{ Attrs, AttrsList, Buffer, CacheKey, Color, Family, FontSystem, Metrics, Placement, SwashCache, SwashContent, }; use image::{GenericImageView, RgbaImage}; +use std::simd::{Simd, num::SimdUint}; /// TODO: properly wrap this pub mod text_lib { diff --git a/src/layout/texture.rs b/core/src/layout/primitive/texture.rs similarity index 97% rename from src/layout/texture.rs rename to core/src/layout/primitive/texture.rs index b34616e..74e3bf0 100644 --- a/src/layout/texture.rs +++ b/core/src/layout/primitive/texture.rs @@ -1,12 +1,13 @@ +use crate::{ + render::TexturePrimitive, + util::{RefCounter, Vec2}, +}; +use image::{DynamicImage, GenericImageView}; use std::{ ops::Index, sync::mpsc::{Receiver, Sender, channel}, }; -use image::{DynamicImage, GenericImageView}; - -use crate::{layout::Vec2, render::TexturePrimitive, util::RefCounter}; - #[derive(Debug, Clone)] pub struct TextureHandle { inner: TexturePrimitive, diff --git a/src/layout/ui.rs b/core/src/layout/ui.rs similarity index 73% rename from src/layout/ui.rs rename to core/src/layout/ui.rs index 5bf6891..0b2c36d 100644 --- a/src/layout/ui.rs +++ b/core/src/layout/ui.rs @@ -1,13 +1,11 @@ -use image::DynamicImage; - use crate::{ - core::{TextEdit, TextEditCtx}, layout::{ - Event, EventFn, EventModule, IdLike, PainterData, PixelRegion, TextureHandle, Vec2, Widget, + Event, EventFn, EventModule, IdLike, PainterData, PixelRegion, TextureHandle, Widget, WidgetId, WidgetInstance, WidgetLike, }, - util::{HashSet, Id}, + util::{Id, Vec2}, }; +use image::DynamicImage; use std::{ any::{Any, TypeId}, ops::{Index, IndexMut}, @@ -16,9 +14,8 @@ use std::{ pub struct Ui { // TODO: make this at least pub(super) - pub(crate) data: PainterData, + pub data: PainterData, root: Option, - updates: HashSet, recv: Receiver, pub(super) send: Sender, full_redraw: bool, @@ -32,11 +29,11 @@ impl Ui { /// useful for debugging pub fn set_label(&mut self, id: &WidgetId, label: String) { - self.data.widgets.data_mut(&id.id).unwrap().label = label; + self.data.widgets.data_mut(&id.id()).unwrap().label = label; } pub fn label(&self, id: &WidgetId) -> &String { - &self.data.widgets.data(&id.id).unwrap().label + &self.data.widgets.data(&id.id()).unwrap().label } pub fn add_widget(&mut self, w: W) -> WidgetId { @@ -45,7 +42,7 @@ impl Ui { pub fn push(&mut self, w: W) -> WidgetId { let id = self.new_id(); - self.data.widgets.insert(id.id, w); + self.data.widgets.insert(id.id(), w); id } @@ -58,11 +55,11 @@ impl Ui { Self::default() } - pub fn get(&self, id: &impl IdLike) -> Option<&W> { + pub fn get(&self, id: &I) -> Option<&I::Widget> { self.data.widgets.get(id) } - pub fn get_mut(&mut self, id: &impl IdLike) -> Option<&mut W> { + pub fn get_mut(&mut self, id: &I) -> Option<&mut I::Widget> { self.data.widgets.get_mut(id) } @@ -87,7 +84,7 @@ impl Ui { self.data .modules .get_mut::>() - .register(id.id, event, f); + .register(id.id(), event, f); } pub fn resize(&mut self, size: impl Into) { @@ -104,7 +101,7 @@ impl Ui { // free before bc nothing should exist self.free(); if let Some(root) = &self.root { - self.data.draw(root.id); + self.data.draw(root.id()); } } @@ -112,26 +109,19 @@ impl Ui { if self.full_redraw { self.redraw_all(); self.full_redraw = false; - } else if !self.updates.is_empty() { + } else if self.data.widgets.has_updates() { self.redraw_updates(); } if self.resized { self.resized = false; - self.redraw_size(); + self.redraw_all(); } } - fn redraw_size(&mut self) { - // let mut ctx = PainterCtx::new(&mut self.data); - // let dep = ctx.px_dependent.clone(); - // for id in dep { - // ctx.redraw(id); - // } - self.redraw_all(); - } - fn redraw_updates(&mut self) { - self.data.redraw(std::mem::take(&mut self.updates)); + let mut updates = std::mem::take(&mut self.data.widgets.updates); + self.data.redraw(&mut updates); + self.data.widgets.updates = updates; self.free(); } @@ -147,7 +137,7 @@ impl Ui { } pub fn needs_redraw(&self) -> bool { - self.full_redraw || !self.updates.is_empty() + self.full_redraw || self.data.widgets.has_updates() } pub fn num_widgets(&self) -> usize { @@ -158,14 +148,6 @@ impl Ui { self.data.active.len() } - pub fn text(&mut self, id: &impl IdLike) -> TextEditCtx<'_> { - self.updates.insert(id.id()); - TextEditCtx { - text: self.data.widgets.get_mut(id).unwrap(), - font_system: &mut self.data.text.font_system, - } - } - pub fn debug_layers(&self) { for ((idx, depth), primitives) in self.data.layers.iter_depth() { let indent = " ".repeat(depth * 2); @@ -178,7 +160,7 @@ impl Ui { } } - pub fn window_region(&self, id: &impl IdLike) -> Option { + pub fn window_region(&self, id: &impl IdLike) -> Option { let region = self.data.active.get(&id.id())?.region; Some(region.to_px(self.data.output_size)) } @@ -191,17 +173,16 @@ impl Ui { } } -impl Index<&WidgetId> for Ui { - type Output = W; +impl Index<&I> for Ui { + type Output = I::Widget; - fn index(&self, id: &WidgetId) -> &Self::Output { + fn index(&self, id: &I) -> &Self::Output { self.get(id).unwrap() } } -impl IndexMut<&WidgetId> for Ui { - fn index_mut(&mut self, id: &WidgetId) -> &mut Self::Output { - self.updates.insert(id.id); +impl IndexMut<&I> for Ui { + fn index_mut(&mut self, id: &I) -> &mut Self::Output { self.get_mut(id).unwrap() } } @@ -222,7 +203,6 @@ impl Default for Ui { Self { data: PainterData::default(), root: Default::default(), - updates: Default::default(), full_redraw: false, send, recv, diff --git a/src/layout/id.rs b/core/src/layout/widget/id.rs similarity index 77% rename from src/layout/id.rs rename to core/src/layout/widget/id.rs index a107b80..551d65f 100644 --- a/src/layout/id.rs +++ b/core/src/layout/widget/id.rs @@ -1,7 +1,7 @@ use std::{any::TypeId, marker::PhantomData, sync::mpsc::Sender}; use crate::{ - layout::{Ui, WidgetLike}, + layout::{Ui, Widget}, util::{Id, RefCounter}, }; @@ -58,7 +58,7 @@ impl Clone for WidgetId { } impl WidgetId { - pub(super) fn new(id: Id, ty: TypeId, send: Sender) -> Self { + pub(crate) fn new(id: Id, ty: TypeId, send: Sender) -> Self { Self { ty, id, @@ -77,7 +77,7 @@ impl WidgetId { unsafe { std::mem::transmute(self) } } - pub fn key(&self) -> Id { + pub fn id(&self) -> Id { self.id } @@ -108,26 +108,6 @@ impl WidgetId { } } -impl WeakWidgetId { - /// should guarantee that widget is still valid to prevent indexing failures - pub(crate) fn strong(&self) -> WidgetId { - let Self { - ty, - id, - ref counter, - ref send, - _pd, - } = *self; - WidgetId { - ty, - id, - counter: counter.clone(), - send: send.clone(), - _pd, - } - } -} - impl Drop for WidgetId { fn drop(&mut self) { if self.counter.drop() { @@ -136,29 +116,12 @@ impl Drop for WidgetId { } } -pub struct IdTag; -pub struct IdFnTag; - pub trait WidgetIdFn: FnOnce(&mut Ui) -> WidgetId {} impl WidgetId> WidgetIdFn for F {} pub trait WidgetRet: FnOnce(&mut Ui) -> WidgetId {} impl WidgetId> WidgetRet for F {} -impl WidgetLike for WidgetId { - type Widget = W; - fn add(self, _: &mut Ui) -> WidgetId { - self - } -} - -impl WidgetId> WidgetLike for F { - type Widget = W; - fn add(self, ui: &mut Ui) -> WidgetId { - self(ui) - } -} - pub trait WidgetIdLike { fn id(self, send: &Sender) -> WidgetId; } @@ -169,11 +132,20 @@ impl WidgetIdLike for &WidgetId { } } -pub trait IdLike { +pub trait IdLike { + type Widget: Widget + 'static; fn id(&self) -> Id; } -impl IdLike for WidgetId { +impl IdLike for WidgetId { + type Widget = W; + fn id(&self) -> Id { + self.id + } +} + +impl IdLike for WeakWidgetId { + type Widget = W; fn id(&self) -> Id { self.id } diff --git a/src/layout/widget.rs b/core/src/layout/widget/like.rs similarity index 50% rename from src/layout/widget.rs rename to core/src/layout/widget/like.rs index 56d18f5..c8e5d84 100644 --- a/src/layout/widget.rs +++ b/core/src/layout/widget/like.rs @@ -1,28 +1,4 @@ -use crate::{ - core::WidgetPtr, - layout::{Len, Painter, SizeCtx, Ui, WidgetId, WidgetIdFn}, -}; - -use std::{any::Any, marker::PhantomData}; - -pub trait Widget: Any { - fn draw(&mut self, painter: &mut Painter); - fn desired_width(&mut self, ctx: &mut SizeCtx) -> Len; - fn desired_height(&mut self, ctx: &mut SizeCtx) -> Len; -} - -impl Widget for () { - fn draw(&mut self, _: &mut Painter) {} - fn desired_width(&mut self, _: &mut SizeCtx) -> Len { - Len::ZERO - } - fn desired_height(&mut self, _: &mut SizeCtx) -> Len { - Len::ZERO - } -} - -pub struct WidgetTag; -pub struct FnTag; +use super::*; pub trait WidgetLike { type Widget: 'static; @@ -48,50 +24,8 @@ pub trait WidgetLike { { ui.set_root(self); } - - fn set_ptr(self, ptr: &WidgetId, ui: &mut Ui) - where - Self: Sized, - { - ui[ptr].inner = Some(self.add(ui).any()); - } } -/// A function that returns a widget given a UI. -/// Useful for defining trait functions on widgets that create a parent widget so that the children -/// don't need to be IDs yet -pub trait WidgetFn: FnOnce(&mut Ui) -> W {} -impl W> WidgetFn for F {} - -impl W> WidgetLike for F { - type Widget = W; - fn add(self, ui: &mut Ui) -> WidgetId { - self(ui).add(ui) - } -} - -impl WidgetLike for W { - type Widget = W; - fn add(self, ui: &mut Ui) -> WidgetId { - ui.add_widget(self) - } -} - -pub struct WidgetArr { - pub arr: [WidgetId; LEN], - _pd: PhantomData, -} - -impl WidgetArr { - pub fn new(arr: [WidgetId; LEN]) -> Self { - Self { - arr, - _pd: PhantomData, - } - } -} - -pub struct ArrTag; pub trait WidgetArrLike { type Ws; fn ui(self, ui: &mut Ui) -> WidgetArr; @@ -142,19 +76,3 @@ impl_widget_arr!(9;A B C D E F G H I); impl_widget_arr!(10;A B C D E F G H I J); impl_widget_arr!(11;A B C D E F G H I J K); impl_widget_arr!(12;A B C D E F G H I J K L); - -pub trait WidgetOption { - fn get(self, ui: &mut Ui) -> Option; -} - -impl WidgetOption for () { - fn get(self, _: &mut Ui) -> Option { - None - } -} - -impl Option> WidgetOption for F { - fn get(self, ui: &mut Ui) -> Option { - self(ui) - } -} diff --git a/core/src/layout/widget/mod.rs b/core/src/layout/widget/mod.rs new file mode 100644 index 0000000..d057e56 --- /dev/null +++ b/core/src/layout/widget/mod.rs @@ -0,0 +1,64 @@ +use crate::layout::{Len, Painter, SizeCtx, Ui}; +use std::{any::Any, marker::PhantomData}; + +mod id; +mod like; +mod tag; +mod widgets; + +pub use id::*; +pub use like::*; +pub use tag::*; +pub use widgets::*; + +pub trait Widget: Any { + fn draw(&mut self, painter: &mut Painter); + fn desired_width(&mut self, ctx: &mut SizeCtx) -> Len; + fn desired_height(&mut self, ctx: &mut SizeCtx) -> Len; +} + +impl Widget for () { + fn draw(&mut self, _: &mut Painter) {} + fn desired_width(&mut self, _: &mut SizeCtx) -> Len { + Len::ZERO + } + fn desired_height(&mut self, _: &mut SizeCtx) -> Len { + Len::ZERO + } +} + +/// A function that returns a widget given a UI. +/// Useful for defining trait functions on widgets that create a parent widget so that the children +/// don't need to be IDs yet +pub trait WidgetFn: FnOnce(&mut Ui) -> W {} +impl W> WidgetFn for F {} + +pub struct WidgetArr { + pub arr: [WidgetId; LEN], + _pd: PhantomData, +} + +impl WidgetArr { + pub fn new(arr: [WidgetId; LEN]) -> Self { + Self { + arr, + _pd: PhantomData, + } + } +} + +pub trait WidgetOption { + fn get(self, ui: &mut Ui) -> Option; +} + +impl WidgetOption for () { + fn get(self, _: &mut Ui) -> Option { + None + } +} + +impl Option> WidgetOption for F { + fn get(self, ui: &mut Ui) -> Option { + self(ui) + } +} diff --git a/core/src/layout/widget/tag.rs b/core/src/layout/widget/tag.rs new file mode 100644 index 0000000..4742943 --- /dev/null +++ b/core/src/layout/widget/tag.rs @@ -0,0 +1,36 @@ +use super::*; + +pub struct ArrTag; + +pub struct WidgetTag; +impl WidgetLike for W { + type Widget = W; + fn add(self, ui: &mut Ui) -> WidgetId { + ui.add_widget(self) + } +} + +pub struct FnTag; +impl W> WidgetLike for F { + type Widget = W; + fn add(self, ui: &mut Ui) -> WidgetId { + self(ui).add(ui) + } +} + +pub struct IdTag; +impl WidgetLike for WidgetId { + type Widget = W; + fn add(self, _: &mut Ui) -> WidgetId { + self + } +} + +pub struct IdFnTag; +impl WidgetId> WidgetLike for F { + type Widget = W; + fn add(self, ui: &mut Ui) -> WidgetId { + self(ui) + } +} + diff --git a/src/layout/widgets.rs b/core/src/layout/widget/widgets.rs similarity index 88% rename from src/layout/widgets.rs rename to core/src/layout/widget/widgets.rs index d29af12..411bc88 100644 --- a/src/layout/widgets.rs +++ b/core/src/layout/widget/widgets.rs @@ -1,10 +1,11 @@ use crate::{ layout::{IdLike, Widget}, - util::{DynBorrower, HashMap, Id, IdTracker}, + util::{DynBorrower, HashMap, HashSet, Id, IdTracker}, }; #[derive(Default)] pub struct Widgets { + pub updates: HashSet, ids: IdTracker, map: HashMap, } @@ -17,11 +18,8 @@ pub struct WidgetData { } impl Widgets { - pub fn new() -> Self { - Self { - ids: IdTracker::default(), - map: HashMap::default(), - } + pub fn has_updates(&self) -> bool { + !self.updates.is_empty() } pub fn get_dyn(&self, id: Id) -> Option<&dyn Widget> { @@ -29,6 +27,7 @@ impl Widgets { } pub fn get_dyn_mut(&mut self, id: Id) -> Option<&mut dyn Widget> { + self.updates.insert(id); Some(self.map.get_mut(&id)?.widget.as_mut()) } @@ -47,11 +46,11 @@ impl Widgets { WidgetWrapper::new(data.widget.as_mut(), &mut data.borrowed) } - pub fn get(&self, id: &impl IdLike) -> Option<&W> { + pub fn get(&self, id: &I) -> Option<&I::Widget> { self.get_dyn(id.id())?.as_any().downcast_ref() } - pub fn get_mut(&mut self, id: &impl IdLike) -> Option<&mut W> { + pub fn get_mut(&mut self, id: &I) -> Option<&mut I::Widget> { self.get_dyn_mut(id.id())?.as_any_mut().downcast_mut() } diff --git a/core/src/lib.rs b/core/src/lib.rs new file mode 100644 index 0000000..5727ed8 --- /dev/null +++ b/core/src/lib.rs @@ -0,0 +1,17 @@ +#![feature(macro_metavar_expr_concat)] +#![feature(const_ops)] +#![feature(const_trait_impl)] +#![feature(const_convert)] +#![feature(map_try_insert)] +#![feature(unboxed_closures)] +#![feature(fn_traits)] +#![feature(const_cmp)] +#![feature(const_destruct)] +#![feature(portable_simd)] +#![feature(associated_type_defaults)] +#![feature(unsize)] +#![feature(coerce_unsized)] + +pub mod layout; +pub mod render; +pub mod util; diff --git a/src/render/data.rs b/core/src/render/data.rs similarity index 100% rename from src/render/data.rs rename to core/src/render/data.rs diff --git a/src/render/mod.rs b/core/src/render/mod.rs similarity index 100% rename from src/render/mod.rs rename to core/src/render/mod.rs diff --git a/src/render/primitive.rs b/core/src/render/primitive.rs similarity index 100% rename from src/render/primitive.rs rename to core/src/render/primitive.rs diff --git a/src/render/shader.wgsl b/core/src/render/shader.wgsl similarity index 100% rename from src/render/shader.wgsl rename to core/src/render/shader.wgsl diff --git a/src/render/texture.rs b/core/src/render/texture.rs similarity index 100% rename from src/render/texture.rs rename to core/src/render/texture.rs diff --git a/src/render/util/mod.rs b/core/src/render/util/mod.rs similarity index 100% rename from src/render/util/mod.rs rename to core/src/render/util/mod.rs diff --git a/src/util/arena.rs b/core/src/util/arena.rs similarity index 100% rename from src/util/arena.rs rename to core/src/util/arena.rs diff --git a/src/util/borrow.rs b/core/src/util/borrow.rs similarity index 100% rename from src/util/borrow.rs rename to core/src/util/borrow.rs diff --git a/src/util/change.rs b/core/src/util/change.rs similarity index 100% rename from src/util/change.rs rename to core/src/util/change.rs diff --git a/src/util/id.rs b/core/src/util/id.rs similarity index 100% rename from src/util/id.rs rename to core/src/util/id.rs diff --git a/src/util/math.rs b/core/src/util/math.rs similarity index 100% rename from src/util/math.rs rename to core/src/util/math.rs diff --git a/src/util/mod.rs b/core/src/util/mod.rs similarity index 59% rename from src/util/mod.rs rename to core/src/util/mod.rs index e014fd6..f2220c3 100644 --- a/src/util/mod.rs +++ b/core/src/util/mod.rs @@ -4,13 +4,15 @@ mod change; mod id; mod math; mod refcount; +mod vec2; -pub(crate) use arena::*; -pub(crate) use borrow::*; +pub use arena::*; +pub use borrow::*; pub use change::*; -pub(crate) use id::*; -pub(crate) use math::*; -pub(crate) use refcount::*; +pub use id::*; +pub use math::*; +pub use refcount::*; +pub use vec2::*; pub type HashMap = fxhash::FxHashMap; pub type HashSet = fxhash::FxHashSet; diff --git a/src/util/refcount.rs b/core/src/util/refcount.rs similarity index 87% rename from src/util/refcount.rs rename to core/src/util/refcount.rs index ee8efb1..77c1660 100644 --- a/src/util/refcount.rs +++ b/core/src/util/refcount.rs @@ -22,6 +22,12 @@ impl RefCounter { } } +impl Default for RefCounter { + fn default() -> Self { + Self::new() + } +} + impl Clone for RefCounter { fn clone(&self) -> Self { self.0.fetch_add(1, Ordering::Release); diff --git a/src/layout/vec2.rs b/core/src/util/vec2.rs similarity index 77% rename from src/layout/vec2.rs rename to core/src/util/vec2.rs index 47e8785..7609861 100644 --- a/src/layout/vec2.rs +++ b/core/src/util/vec2.rs @@ -1,8 +1,5 @@ -use crate::{ - layout::UiNum, - util::{DivOr, impl_op}, -}; -use std::{hash::Hash, marker::Destruct, ops::*}; +use crate::util::{DivOr, impl_op}; +use std::{hash::Hash, ops::*}; #[repr(C)] #[derive(Clone, Copy, PartialEq, Default, bytemuck::Pod, bytemuck::Zeroable)] @@ -20,10 +17,6 @@ impl Hash for Vec2 { } } -pub const fn vec2(x: impl const UiNum, y: impl const UiNum) -> Vec2 { - Vec2::new(x.to_f32(), y.to_f32()) -} - impl Vec2 { pub const ZERO: Self = Self::new(0.0, 0.0); pub const ONE: Self = Self::new(1.0, 1.0); @@ -68,15 +61,6 @@ impl Vec2 { } } -impl const From for Vec2 { - fn from(v: T) -> Self { - Self { - x: v.to_f32(), - y: v.to_f32(), - } - } -} - // this version looks kinda cool... is it more readable? more annoying to copy and change though impl_op!(impl Add for Vec2: add x y); impl_op!(Vec2 Sub sub; x y); @@ -102,18 +86,6 @@ impl Neg for Vec2 { } } -impl const From<(T, U)> for Vec2 -where - (T, U): const Destruct, -{ - fn from((x, y): (T, U)) -> Self { - Self { - x: x.to_f32(), - y: y.to_f32(), - } - } -} - impl std::fmt::Debug for Vec2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {})", self.x, self.y) diff --git a/examples/minimal.rs b/examples/minimal.rs index 60af299..dd468f9 100644 --- a/examples/minimal.rs +++ b/examples/minimal.rs @@ -1,4 +1,4 @@ -use iris::{prelude::*, winit::*}; +use iris::prelude::*; fn main() { DefaultApp::::run(); diff --git a/macro/Cargo.toml b/macro/Cargo.toml new file mode 100644 index 0000000..88997fa --- /dev/null +++ b/macro/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "iris-macro" +version.workspace = true +edition.workspace = true + +[dependencies] +quote = "1.0.42" +syn = { version = "2.0.111", features = ["full"] } + +[lib] +proc-macro = true diff --git a/macro/src/lib.rs b/macro/src/lib.rs new file mode 100644 index 0000000..ede2261 --- /dev/null +++ b/macro/src/lib.rs @@ -0,0 +1,77 @@ +extern crate proc_macro; +use proc_macro::TokenStream; +use quote::quote; +use syn::{ + Attribute, Block, Ident, ItemTrait, Signature, Token, Visibility, + parse::{Parse, ParseStream, Result}, + parse_macro_input, parse_quote, +}; + +struct Input { + attrs: Vec, + vis: Visibility, + name: Ident, + fns: Vec, +} + +struct InputFn { + sig: Signature, + body: Block, +} + +impl Parse for Input { + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + let vis = input.parse()?; + input.parse::()?; + let name = input.parse()?; + input.parse::()?; + let mut fns = Vec::new(); + while !input.is_empty() { + let sig = input.parse()?; + let body = input.parse()?; + fns.push(InputFn { sig, body }) + } + if !input.is_empty() { + input.error("function expected"); + } + Ok(Input { + attrs, + vis, + name, + fns, + }) + } +} + +#[proc_macro] +pub fn widget_trait(input: TokenStream) -> TokenStream { + let Input { + attrs, + vis, + name, + fns, + } = parse_macro_input!(input as Input); + + let sigs: Vec<_> = fns.iter().map(|f| f.sig.clone()).collect(); + let impls: Vec<_> = fns + .iter() + .map(|InputFn { sig, body }| quote! { #sig #body }) + .collect(); + + let mut trai: ItemTrait = parse_quote!( + #vis trait #name, Tag> { + #(#sigs;)* + } + ); + + trai.attrs = attrs; + + TokenStream::from(quote! { + #trai + + impl, Tag> #name for WL { + #(#impls)* + } + }) +} diff --git a/src/bin/test/main.rs b/src/bin/test/main.rs index 2cd7af8..f8aa1ee 100644 --- a/src/bin/test/main.rs +++ b/src/bin/test/main.rs @@ -1,8 +1,5 @@ use cosmic_text::Family; -use iris::{ - prelude::*, - winit::{attr::Selectable, event::Submit, *}, -}; +use iris::prelude::*; use len_fns::*; use winit::event::WindowEvent; @@ -110,7 +107,7 @@ impl DefaultAppState for Client { .size(30) .attr::(()) .on(Submit, move |ctx| { - let content = ctx.ui.text(ctx.id).take(); + let content = ctx.id.edit(ctx.ui).take(); let text = wtext(content) .editable(false) .size(30) diff --git a/src/winit/app.rs b/src/default/app.rs similarity index 100% rename from src/winit/app.rs rename to src/default/app.rs diff --git a/src/winit/attr.rs b/src/default/attr.rs similarity index 93% rename from src/winit/attr.rs rename to src/default/attr.rs index e89a9d6..01e0fe5 100644 --- a/src/winit/attr.rs +++ b/src/default/attr.rs @@ -1,10 +1,10 @@ -use crate::{prelude::*, winit::UiState}; +use crate::{default::UiState, prelude::*}; use std::time::{Duration, Instant}; use winit::dpi::{LogicalPosition, LogicalSize}; pub struct Selector; -impl WidgetAttr for Selector { +impl WidgetAttr for Selector { type Input = WidgetId; fn run(ui: &mut Ui, container: &WidgetId, id: Self::Input) { @@ -42,7 +42,7 @@ fn select(ui: &mut Ui, id: WidgetId, state: &mut UiState, data: Cursor let now = Instant::now(); let recent = (now - state.last_click) < Duration::from_millis(300); state.last_click = now; - ui.text(&id) + id.edit(ui) .select(data.cursor, data.size, data.sense.is_dragging(), recent); if let Some(region) = ui.window_region(&id) { state.window.set_ime_allowed(true); diff --git a/src/winit/event.rs b/src/default/event.rs similarity index 57% rename from src/winit/event.rs rename to src/default/event.rs index 51cc925..22fe1dd 100644 --- a/src/winit/event.rs +++ b/src/default/event.rs @@ -2,14 +2,8 @@ use crate::layout::DefaultEvent; #[derive(Eq, PartialEq, Hash, Clone)] pub struct Submit; +impl DefaultEvent for Submit {} #[derive(Eq, PartialEq, Hash, Clone)] pub struct Edited; - -impl DefaultEvent for Submit { - type Data = (); -} - -impl DefaultEvent for Edited { - type Data = (); -} +impl DefaultEvent for Edited {} diff --git a/src/winit/input.rs b/src/default/input.rs similarity index 96% rename from src/winit/input.rs rename to src/default/input.rs index 811653f..4aa96b7 100644 --- a/src/winit/input.rs +++ b/src/default/input.rs @@ -1,8 +1,4 @@ -use crate::{ - core::{CursorState, Modifiers}, - layout::Vec2, - winit::UiState, -}; +use crate::prelude::*; use winit::{ event::{MouseButton, MouseScrollDelta, WindowEvent}, keyboard::{Key, NamedKey}, diff --git a/src/winit/mod.rs b/src/default/mod.rs similarity index 95% rename from src/winit/mod.rs rename to src/default/mod.rs index 774e3c2..9ccf16c 100644 --- a/src/winit/mod.rs +++ b/src/default/mod.rs @@ -1,6 +1,4 @@ use crate::prelude::*; -use crate::winit::event::{Edited, Submit}; -use crate::winit::{input::Input, render::UiRenderer}; use arboard::Clipboard; use std::sync::Arc; use std::time::Instant; @@ -9,12 +7,16 @@ use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; use winit::window::{Window, WindowAttributes}; mod app; -pub mod attr; -pub mod event; -pub mod input; -pub mod render; +mod attr; +mod event; +mod input; +mod render; pub use app::*; +pub use attr::*; +pub use event::*; +pub use input::*; +pub use render::*; pub type Proxy = EventLoopProxy; pub type DefaultApp = App>; @@ -105,7 +107,7 @@ impl AppState for DefaultState { if old != ui_state.focus && let Some(old) = old { - ui.text(&old).deselect(); + old.edit(ui).deselect(); } match &event { WindowEvent::CloseRequested => event_loop.exit(), @@ -123,7 +125,7 @@ impl AppState for DefaultState { && event.state.is_pressed() { let sel = &sel.clone(); - let mut text = ui.text(sel); + let mut text = sel.edit(ui); match text.apply_event(event, &ui_state.input.modifiers) { TextInputResult::Unfocus => { ui_state.focus = None; @@ -152,7 +154,7 @@ impl AppState for DefaultState { } WindowEvent::Ime(ime) => { if let Some(sel) = &ui_state.focus { - let mut text = ui.text(sel); + let mut text = sel.edit(ui); match ime { Ime::Enabled | Ime::Disabled => (), Ime::Preedit(content, _pos) => { diff --git a/src/winit/render.rs b/src/default/render.rs similarity index 100% rename from src/winit/render.rs rename to src/default/render.rs diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..9134c19 --- /dev/null +++ b/src/event.rs @@ -0,0 +1,67 @@ +use crate::prelude::*; + +// TODO: naming in here is a bit weird like eventable +#[macro_export] +macro_rules! event_ctx { + ($ty: ty) => { + mod local_event_trait { + use super::*; + #[allow(unused_imports)] + use $crate::prelude::*; + + pub trait EventableCtx { + fn on( + self, + event: E, + f: impl WidgetEventFn, + ) -> impl WidgetIdFn + EventableCtx; + } + + impl, Tag> EventableCtx for WL { + fn on( + self, + event: E, + f: impl WidgetEventFn<$ty, E::Data, WL::Widget>, + ) -> impl WidgetIdFn + EventableCtx { + eventable::Eventable::on(self, event, f) + } + } + } + use local_event_trait::*; + }; +} +pub use event_ctx; + +pub mod eventable { + use super::*; + + pub trait Eventable { + fn on( + self, + event: E, + f: impl WidgetEventFn, + ) -> impl WidgetIdFn + Eventable; + } + + impl, Tag> Eventable for WL { + fn on( + self, + event: E, + f: impl WidgetEventFn, + ) -> impl WidgetIdFn { + move |ui| { + let id = self.add(ui); + let id_ = id.weak(); + ui.register_event(&id, event, move |ctx| { + f(EventIdCtx { + id: &id_, + state: ctx.state, + data: ctx.data, + ui: ctx.ui, + }); + }); + id + } + } + } +} diff --git a/src/layout/mask.rs b/src/layout/mask.rs deleted file mode 100644 index 2860ac5..0000000 --- a/src/layout/mask.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! tree structure for masking - -use crate::layout::UiRegion; - -pub struct Masks { - data: Vec, -} - -#[repr(C)] -#[derive(Clone, Copy)] -pub struct MaskPtr(u32); - -#[repr(C)] -pub struct MaskNode { - /// TODO: this is just a rect for now, - /// but would like to support arbitrary masks - /// at some point; custom shader - /// would probably handle that case - /// bc you'd need to render to a special target - /// anyways - region: UiRegion, - prev: MaskPtr, -} - -impl MaskPtr { - const NONE: Self = Self(u32::MAX); -} - -impl Masks { - pub fn push(&mut self, parent: MaskPtr, region: UiRegion) -> MaskPtr { - match parent.0 { - _ => { - } - u32::MAX => { - let i = self.data.len(); - self.data.push(MaskNode { - region, - prev: parent, - }); - MaskPtr(i as u32) - } - } - } - - pub fn pop(&mut self, i: usize) {} -} diff --git a/src/layout/num.rs b/src/layout/num.rs deleted file mode 100644 index c46b013..0000000 --- a/src/layout/num.rs +++ /dev/null @@ -1,21 +0,0 @@ -pub const trait UiNum { - fn to_f32(self) -> f32; -} - -impl const UiNum for f32 { - fn to_f32(self) -> f32 { - self - } -} - -impl const UiNum for u32 { - fn to_f32(self) -> f32 { - self as f32 - } -} - -impl const UiNum for i32 { - fn to_f32(self) -> f32 { - self as f32 - } -} diff --git a/src/lib.rs b/src/lib.rs index 61bfdf3..cc04dcd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,24 +1,23 @@ -#![feature(macro_metavar_expr_concat)] -#![feature(const_ops)] -#![feature(const_trait_impl)] -#![feature(const_convert)] -#![feature(map_try_insert)] #![feature(unboxed_closures)] #![feature(fn_traits)] -#![feature(const_cmp)] -#![feature(const_destruct)] -#![feature(portable_simd)] #![feature(gen_blocks)] #![feature(associated_type_defaults)] -pub mod core; -pub mod layout; -pub mod render; -pub mod util; -pub mod winit; +mod default; +mod event; +mod widget; + +pub use iris_core::*; +pub use iris_macro::*; pub mod prelude { - pub use crate::core::*; - pub use crate::layout::*; - pub use crate::render::*; + use super::*; + pub use default::*; + pub use event::*; + pub use iris_macro::*; + pub use layout::*; + pub use render::*; + pub use widget::*; + + pub use super::util::Vec2; } diff --git a/src/core/event.rs b/src/widget/event.rs similarity index 100% rename from src/core/event.rs rename to src/widget/event.rs diff --git a/src/core/image.rs b/src/widget/image.rs similarity index 100% rename from src/core/image.rs rename to src/widget/image.rs diff --git a/src/core/mask.rs b/src/widget/mask.rs similarity index 100% rename from src/core/mask.rs rename to src/widget/mask.rs diff --git a/src/core/mod.rs b/src/widget/mod.rs similarity index 100% rename from src/core/mod.rs rename to src/widget/mod.rs diff --git a/src/core/position/align.rs b/src/widget/position/align.rs similarity index 100% rename from src/core/position/align.rs rename to src/widget/position/align.rs diff --git a/src/core/position/layer.rs b/src/widget/position/layer.rs similarity index 100% rename from src/core/position/layer.rs rename to src/widget/position/layer.rs diff --git a/src/core/position/max_size.rs b/src/widget/position/max_size.rs similarity index 100% rename from src/core/position/max_size.rs rename to src/widget/position/max_size.rs diff --git a/src/core/position/mod.rs b/src/widget/position/mod.rs similarity index 100% rename from src/core/position/mod.rs rename to src/widget/position/mod.rs diff --git a/src/core/position/offset.rs b/src/widget/position/offset.rs similarity index 100% rename from src/core/position/offset.rs rename to src/widget/position/offset.rs diff --git a/src/core/position/pad.rs b/src/widget/position/pad.rs similarity index 100% rename from src/core/position/pad.rs rename to src/widget/position/pad.rs diff --git a/src/core/position/scroll.rs b/src/widget/position/scroll.rs similarity index 100% rename from src/core/position/scroll.rs rename to src/widget/position/scroll.rs diff --git a/src/core/position/sized.rs b/src/widget/position/sized.rs similarity index 100% rename from src/core/position/sized.rs rename to src/widget/position/sized.rs diff --git a/src/core/position/span.rs b/src/widget/position/span.rs similarity index 100% rename from src/core/position/span.rs rename to src/widget/position/span.rs diff --git a/src/core/position/stack.rs b/src/widget/position/stack.rs similarity index 100% rename from src/core/position/stack.rs rename to src/widget/position/stack.rs diff --git a/src/core/ptr.rs b/src/widget/ptr.rs similarity index 100% rename from src/core/ptr.rs rename to src/widget/ptr.rs diff --git a/src/core/rect.rs b/src/widget/rect.rs similarity index 100% rename from src/core/rect.rs rename to src/widget/rect.rs diff --git a/src/core/sense.rs b/src/widget/sense.rs similarity index 95% rename from src/core/sense.rs rename to src/widget/sense.rs index 423bb90..75bbb28 100644 --- a/src/core/sense.rs +++ b/src/widget/sense.rs @@ -6,8 +6,8 @@ use std::{ }; use crate::{ - layout::{UiModule, UiRegion, Vec2}, - util::{HashMap, Id}, + layout::{UiModule, UiRegion}, + util::{HashMap, Id, Vec2}, }; #[derive(Clone, Copy, PartialEq)] @@ -166,8 +166,12 @@ impl CursorModule { } } -impl Ui { - pub fn run_sensors( +pub trait SensorUi { + fn run_sensors(&mut self, ctx: &mut Ctx, cursor: &CursorState, window_size: Vec2); +} + +impl SensorUi for Ui { + fn run_sensors( &mut self, ctx: &mut Ctx, cursor: &CursorState, @@ -205,7 +209,11 @@ impl CursorModule { scroll_delta: cursor.scroll_delta, sense, }; - (sensor.f)(EventCtx { ui, state: ctx, data }); + (sensor.f)(EventCtx { + ui, + state: ctx, + data, + }); } } } diff --git a/src/core/text/build.rs b/src/widget/text/build.rs similarity index 100% rename from src/core/text/build.rs rename to src/widget/text/build.rs diff --git a/src/core/text/edit.rs b/src/widget/text/edit.rs similarity index 98% rename from src/core/text/edit.rs rename to src/widget/text/edit.rs index c176e05..b8c9d7b 100644 --- a/src/core/text/edit.rs +++ b/src/widget/text/edit.rs @@ -610,3 +610,16 @@ impl DerefMut for TextEdit { &mut self.view } } + +pub trait TextEditable { + fn edit<'a>(&self, ui: &'a mut Ui) -> TextEditCtx<'a>; +} + +impl> TextEditable for I { + fn edit<'a>(&self, ui: &'a mut Ui) -> TextEditCtx<'a> { + TextEditCtx { + text: ui.data.widgets.get_mut(self).unwrap(), + font_system: &mut ui.data.text.font_system, + } + } +} diff --git a/src/core/text/mod.rs b/src/widget/text/mod.rs similarity index 100% rename from src/core/text/mod.rs rename to src/widget/text/mod.rs diff --git a/src/core/trait_fns.rs b/src/widget/trait_fns.rs similarity index 100% rename from src/core/trait_fns.rs rename to src/widget/trait_fns.rs