refactor project structure (start of redoing atomic branch without atomics)
This commit is contained in:
1 parent
38266debb6
commit
2dc5b0f62c
76 files changed
+540
-442
No files matched your search
Generated
+24
-4
@@ -1042,16 +1042,36 @@ name = "iris"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arboard",
|
"arboard",
|
||||||
"bytemuck",
|
|
||||||
"cosmic-text",
|
"cosmic-text",
|
||||||
"fxhash",
|
|
||||||
"image",
|
"image",
|
||||||
|
"iris-core",
|
||||||
|
"iris-macro",
|
||||||
"pollster",
|
"pollster",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"winit",
|
"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]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@@ -2401,9 +2421,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.110"
|
version = "2.0.111"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
|
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
+23
-4
@@ -1,12 +1,30 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "iris"
|
name = "iris"
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
default-run = "test"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[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"
|
pollster = "0.4.0"
|
||||||
winit = "0.30.12"
|
winit = "0.30.12"
|
||||||
wgpu = "27.0.1"
|
wgpu = "27.0.1"
|
||||||
@@ -15,5 +33,6 @@ image = "0.25.6"
|
|||||||
cosmic-text = "0.15.0"
|
cosmic-text = "0.15.0"
|
||||||
unicode-segmentation = "1.12.0"
|
unicode-segmentation = "1.12.0"
|
||||||
fxhash = "0.2.1"
|
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" }
|
||||||
@@ -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 }
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
|||||||
use std::{hash::Hash, rc::Rc};
|
use std::{hash::Hash, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
layout::{IdFnTag, Ui, UiModule, WidgetId, WidgetIdFn, WidgetLike},
|
layout::{Ui, UiModule, WeakWidgetId, WidgetId},
|
||||||
util::{HashMap, Id},
|
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 type ECtx<'a, Ctx, Data, W> = EventIdCtx<'a, Ctx, Data, W>;
|
||||||
pub struct EventIdCtx<'a, Ctx, Data, W> {
|
pub struct EventIdCtx<'a, Ctx, Data, W> {
|
||||||
pub id: &'a WidgetId<W>,
|
pub id: &'a WeakWidgetId<W>,
|
||||||
pub ui: &'a mut Ui,
|
pub ui: &'a mut Ui,
|
||||||
pub state: &'a mut Ctx,
|
pub state: &'a mut Ctx,
|
||||||
pub data: Data,
|
pub data: Data,
|
||||||
@@ -30,74 +30,8 @@ impl<F: Fn(EventCtx<Ctx, Data>) + 'static, Ctx, Data> EventFn<Ctx, Data> for F {
|
|||||||
pub trait WidgetEventFn<Ctx, Data, W>: Fn(EventIdCtx<Ctx, Data, W>) + 'static {}
|
pub trait WidgetEventFn<Ctx, Data, W>: Fn(EventIdCtx<Ctx, Data, W>) + 'static {}
|
||||||
impl<F: Fn(EventIdCtx<Ctx, Data, W>) + 'static, Ctx, Data, W> WidgetEventFn<Ctx, Data, W> for F {}
|
impl<F: Fn(EventIdCtx<Ctx, Data, W>) + 'static, Ctx, Data, W> WidgetEventFn<Ctx, Data, W> 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<W, Tag, Ctx: 'static> {
|
|
||||||
fn on<E: Event>(
|
|
||||||
self,
|
|
||||||
event: E,
|
|
||||||
f: impl WidgetEventFn<Ctx, E::Data, W>,
|
|
||||||
) -> impl WidgetIdFn<W> + EventableCtx<W, IdFnTag, Ctx>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<WL: WidgetLike<Tag>, Tag> EventableCtx<WL::Widget, Tag, $ty> for WL {
|
|
||||||
fn on<E: Event>(
|
|
||||||
self,
|
|
||||||
event: E,
|
|
||||||
f: impl WidgetEventFn<$ty, E::Data, WL::Widget>,
|
|
||||||
) -> impl WidgetIdFn<WL::Widget> + EventableCtx<WL::Widget, IdFnTag, $ty> {
|
|
||||||
eventable::Eventable::on(self, event, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
use local_event_trait::*;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
pub use event_ctx;
|
|
||||||
|
|
||||||
pub mod eventable {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub trait Eventable<W, Tag> {
|
|
||||||
fn on<E: Event, Ctx: 'static>(
|
|
||||||
self,
|
|
||||||
event: E,
|
|
||||||
f: impl WidgetEventFn<Ctx, E::Data, W>,
|
|
||||||
) -> impl WidgetIdFn<W> + Eventable<W, IdFnTag>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<WL: WidgetLike<Tag>, Tag> Eventable<WL::Widget, Tag> for WL {
|
|
||||||
fn on<E: Event, Ctx: 'static>(
|
|
||||||
self,
|
|
||||||
event: E,
|
|
||||||
f: impl WidgetEventFn<Ctx, E::Data, WL::Widget>,
|
|
||||||
) -> impl WidgetIdFn<WL::Widget> {
|
|
||||||
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 {
|
pub trait DefaultEvent: Hash + Eq + 'static {
|
||||||
type Data: Clone;
|
type Data: Clone = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: DefaultEvent> Event for E {
|
impl<E: DefaultEvent> Event for E {
|
||||||
@@ -203,7 +137,7 @@ impl Ui {
|
|||||||
.data
|
.data
|
||||||
.modules
|
.modules
|
||||||
.get_mut::<E::Module<Ctx>>()
|
.get_mut::<E::Module<Ctx>>()
|
||||||
.run(&id.id, event)
|
.run(&id.id(), event)
|
||||||
{
|
{
|
||||||
f(EventCtx {
|
f(EventCtx {
|
||||||
ui: self,
|
ui: self,
|
||||||
@@ -1,33 +1,21 @@
|
|||||||
mod color;
|
mod attr;
|
||||||
mod event;
|
mod event;
|
||||||
mod id;
|
|
||||||
mod layer;
|
|
||||||
mod module;
|
mod module;
|
||||||
mod num;
|
mod num;
|
||||||
mod orientation;
|
mod orientation;
|
||||||
mod painter;
|
mod painter;
|
||||||
mod text;
|
mod primitive;
|
||||||
mod texture;
|
|
||||||
mod ui;
|
mod ui;
|
||||||
mod attr;
|
|
||||||
mod vec2;
|
|
||||||
mod widget;
|
mod widget;
|
||||||
mod widgets;
|
|
||||||
|
|
||||||
pub use color::*;
|
pub use attr::*;
|
||||||
pub use event::*;
|
pub use event::*;
|
||||||
pub use id::*;
|
|
||||||
pub use layer::*;
|
|
||||||
pub use module::*;
|
pub use module::*;
|
||||||
pub use num::*;
|
pub use num::*;
|
||||||
pub use orientation::*;
|
pub use orientation::*;
|
||||||
pub use painter::*;
|
pub use painter::*;
|
||||||
pub use text::*;
|
pub use primitive::*;
|
||||||
pub use texture::*;
|
|
||||||
pub use ui::*;
|
pub use ui::*;
|
||||||
pub use attr::*;
|
|
||||||
pub use vec2::*;
|
|
||||||
pub use widget::*;
|
pub use widget::*;
|
||||||
pub use widgets::*;
|
|
||||||
|
|
||||||
pub type UiColor = Color<u8>;
|
pub type UiColor = Color<u8>;
|
||||||
File renamed without changes.
@@ -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<T: const UiNum + Copy> const From<T> for Vec2 {
|
||||||
|
fn from(v: T) -> Self {
|
||||||
|
Self {
|
||||||
|
x: v.to_f32(),
|
||||||
|
y: v.to_f32(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: const UiNum, U: const UiNum> 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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -3,7 +3,7 @@ mod axis;
|
|||||||
mod len;
|
mod len;
|
||||||
mod pos;
|
mod pos;
|
||||||
|
|
||||||
use super::vec2::*;
|
use crate::util::Vec2;
|
||||||
|
|
||||||
pub use align::*;
|
pub use align::*;
|
||||||
pub use axis::*;
|
pub use axis::*;
|
||||||
File renamed without changes.
@@ -1,10 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
layout::{
|
layout::{
|
||||||
Axis, Len, Modules, PrimitiveLayers, RenderedText, Size, TextAttrs, TextBuffer, TextData,
|
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},
|
render::{Mask, MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst},
|
||||||
util::{HashMap, HashSet, Id, TrackedArena},
|
util::{HashMap, HashSet, Id, TrackedArena, Vec2},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// makes your surfaces look pretty
|
/// makes your surfaces look pretty
|
||||||
@@ -33,7 +33,7 @@ struct PainterCtx<'a> {
|
|||||||
pub modules: &'a mut Modules,
|
pub modules: &'a mut Modules,
|
||||||
pub cache_width: HashMap<Id, (UiVec2, Len)>,
|
pub cache_width: HashMap<Id, (UiVec2, Len)>,
|
||||||
pub cache_height: HashMap<Id, (UiVec2, Len)>,
|
pub cache_height: HashMap<Id, (UiVec2, Len)>,
|
||||||
pub needs_redraw: HashSet<Id>,
|
pub needs_redraw: &'a mut HashSet<Id>,
|
||||||
draw_started: HashSet<Id>,
|
draw_started: HashSet<Id>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ impl<'a> PainterCtx<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PainterData {
|
impl PainterData {
|
||||||
fn ctx(&mut self, needs_redraw: HashSet<Id>) -> PainterCtx<'_> {
|
fn ctx<'a>(&'a mut self, needs_redraw: &'a mut HashSet<Id>) -> PainterCtx<'a> {
|
||||||
PainterCtx {
|
PainterCtx {
|
||||||
widgets: &self.widgets,
|
widgets: &self.widgets,
|
||||||
active: &mut self.active,
|
active: &mut self.active,
|
||||||
@@ -341,13 +341,14 @@ impl PainterData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&mut self, id: Id) {
|
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.draw_started.clear();
|
||||||
ctx.layers.clear();
|
ctx.layers.clear();
|
||||||
ctx.draw_inner(0, id, UiRegion::FULL, None, MaskIdx::NONE, None);
|
ctx.draw_inner(0, id, UiRegion::FULL, None, MaskIdx::NONE, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redraw(&mut self, ids: HashSet<Id>) {
|
pub fn redraw(&mut self, ids: &mut HashSet<Id>) {
|
||||||
let mut ctx = self.ctx(ids);
|
let mut ctx = self.ctx(ids);
|
||||||
while let Some(&id) = ctx.needs_redraw.iter().next() {
|
while let Some(&id) = ctx.needs_redraw.iter().next() {
|
||||||
ctx.redraw(id);
|
ctx.redraw(id);
|
||||||
@@ -399,9 +400,9 @@ impl<'a, 'c> Painter<'a, 'c> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn widget_at<W>(&mut self, id: &WidgetId<W>, region: UiRegion) {
|
fn widget_at<W>(&mut self, id: &WidgetId<W>, region: UiRegion) {
|
||||||
self.children.push(id.id);
|
self.children.push(id.id());
|
||||||
self.ctx
|
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) {
|
pub fn texture_within(&mut self, handle: &TextureHandle, region: UiRegion) {
|
||||||
@@ -552,11 +553,11 @@ impl SizeCtx<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn width<W>(&mut self, id: &WidgetId<W>) -> Len {
|
pub fn width<W>(&mut self, id: &WidgetId<W>) -> Len {
|
||||||
self.width_inner(id.id)
|
self.width_inner(id.id())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height<W>(&mut self, id: &WidgetId<W>) -> Len {
|
pub fn height<W>(&mut self, id: &WidgetId<W>) -> Len {
|
||||||
self.height_inner(id.id)
|
self.height_inner(id.id())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len_axis<W>(&mut self, id: &WidgetId<W>, axis: Axis) -> Len {
|
pub fn len_axis<W>(&mut self, id: &WidgetId<W>, axis: Axis) -> Len {
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,9 @@
|
|||||||
|
mod color;
|
||||||
|
mod layer;
|
||||||
|
mod text;
|
||||||
|
mod texture;
|
||||||
|
|
||||||
|
pub use color::*;
|
||||||
|
pub use layer::*;
|
||||||
|
pub use text::*;
|
||||||
|
pub use texture::*;
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
use std::simd::{Simd, num::SimdUint};
|
use crate::{
|
||||||
|
layout::{Align, RegionAlign, TextureHandle, Textures, UiColor},
|
||||||
use crate::layout::{Align, RegionAlign, TextureHandle, Textures, UiColor, Vec2};
|
util::Vec2,
|
||||||
|
};
|
||||||
use cosmic_text::{
|
use cosmic_text::{
|
||||||
Attrs, AttrsList, Buffer, CacheKey, Color, Family, FontSystem, Metrics, Placement, SwashCache,
|
Attrs, AttrsList, Buffer, CacheKey, Color, Family, FontSystem, Metrics, Placement, SwashCache,
|
||||||
SwashContent,
|
SwashContent,
|
||||||
};
|
};
|
||||||
use image::{GenericImageView, RgbaImage};
|
use image::{GenericImageView, RgbaImage};
|
||||||
|
use std::simd::{Simd, num::SimdUint};
|
||||||
|
|
||||||
/// TODO: properly wrap this
|
/// TODO: properly wrap this
|
||||||
pub mod text_lib {
|
pub mod text_lib {
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
|
use crate::{
|
||||||
|
render::TexturePrimitive,
|
||||||
|
util::{RefCounter, Vec2},
|
||||||
|
};
|
||||||
|
use image::{DynamicImage, GenericImageView};
|
||||||
use std::{
|
use std::{
|
||||||
ops::Index,
|
ops::Index,
|
||||||
sync::mpsc::{Receiver, Sender, channel},
|
sync::mpsc::{Receiver, Sender, channel},
|
||||||
};
|
};
|
||||||
|
|
||||||
use image::{DynamicImage, GenericImageView};
|
|
||||||
|
|
||||||
use crate::{layout::Vec2, render::TexturePrimitive, util::RefCounter};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TextureHandle {
|
pub struct TextureHandle {
|
||||||
inner: TexturePrimitive,
|
inner: TexturePrimitive,
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
use image::DynamicImage;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{TextEdit, TextEditCtx},
|
|
||||||
layout::{
|
layout::{
|
||||||
Event, EventFn, EventModule, IdLike, PainterData, PixelRegion, TextureHandle, Vec2, Widget,
|
Event, EventFn, EventModule, IdLike, PainterData, PixelRegion, TextureHandle, Widget,
|
||||||
WidgetId, WidgetInstance, WidgetLike,
|
WidgetId, WidgetInstance, WidgetLike,
|
||||||
},
|
},
|
||||||
util::{HashSet, Id},
|
util::{Id, Vec2},
|
||||||
};
|
};
|
||||||
|
use image::DynamicImage;
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
ops::{Index, IndexMut},
|
ops::{Index, IndexMut},
|
||||||
@@ -16,9 +14,8 @@ use std::{
|
|||||||
|
|
||||||
pub struct Ui {
|
pub struct Ui {
|
||||||
// TODO: make this at least pub(super)
|
// TODO: make this at least pub(super)
|
||||||
pub(crate) data: PainterData,
|
pub data: PainterData,
|
||||||
root: Option<WidgetId>,
|
root: Option<WidgetId>,
|
||||||
updates: HashSet<Id>,
|
|
||||||
recv: Receiver<Id>,
|
recv: Receiver<Id>,
|
||||||
pub(super) send: Sender<Id>,
|
pub(super) send: Sender<Id>,
|
||||||
full_redraw: bool,
|
full_redraw: bool,
|
||||||
@@ -32,11 +29,11 @@ impl Ui {
|
|||||||
|
|
||||||
/// useful for debugging
|
/// useful for debugging
|
||||||
pub fn set_label<W>(&mut self, id: &WidgetId<W>, label: String) {
|
pub fn set_label<W>(&mut self, id: &WidgetId<W>, 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<W>(&self, id: &WidgetId<W>) -> &String {
|
pub fn label<W>(&self, id: &WidgetId<W>) -> &String {
|
||||||
&self.data.widgets.data(&id.id).unwrap().label
|
&self.data.widgets.data(&id.id()).unwrap().label
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_widget<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
pub fn add_widget<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
||||||
@@ -45,7 +42,7 @@ impl Ui {
|
|||||||
|
|
||||||
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
||||||
let id = self.new_id();
|
let id = self.new_id();
|
||||||
self.data.widgets.insert(id.id, w);
|
self.data.widgets.insert(id.id(), w);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,11 +55,11 @@ impl Ui {
|
|||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<W: Widget>(&self, id: &impl IdLike<W>) -> Option<&W> {
|
pub fn get<I: IdLike>(&self, id: &I) -> Option<&I::Widget> {
|
||||||
self.data.widgets.get(id)
|
self.data.widgets.get(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut<W: Widget>(&mut self, id: &impl IdLike<W>) -> Option<&mut W> {
|
pub fn get_mut<I: IdLike>(&mut self, id: &I) -> Option<&mut I::Widget> {
|
||||||
self.data.widgets.get_mut(id)
|
self.data.widgets.get_mut(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +84,7 @@ impl Ui {
|
|||||||
self.data
|
self.data
|
||||||
.modules
|
.modules
|
||||||
.get_mut::<E::Module<Ctx>>()
|
.get_mut::<E::Module<Ctx>>()
|
||||||
.register(id.id, event, f);
|
.register(id.id(), event, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, size: impl Into<Vec2>) {
|
pub fn resize(&mut self, size: impl Into<Vec2>) {
|
||||||
@@ -104,7 +101,7 @@ impl Ui {
|
|||||||
// free before bc nothing should exist
|
// free before bc nothing should exist
|
||||||
self.free();
|
self.free();
|
||||||
if let Some(root) = &self.root {
|
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 {
|
if self.full_redraw {
|
||||||
self.redraw_all();
|
self.redraw_all();
|
||||||
self.full_redraw = false;
|
self.full_redraw = false;
|
||||||
} else if !self.updates.is_empty() {
|
} else if self.data.widgets.has_updates() {
|
||||||
self.redraw_updates();
|
self.redraw_updates();
|
||||||
}
|
}
|
||||||
if self.resized {
|
if self.resized {
|
||||||
self.resized = false;
|
self.resized = false;
|
||||||
self.redraw_size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
self.redraw_all();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn redraw_updates(&mut self) {
|
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();
|
self.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +137,7 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn needs_redraw(&self) -> bool {
|
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 {
|
pub fn num_widgets(&self) -> usize {
|
||||||
@@ -158,14 +148,6 @@ impl Ui {
|
|||||||
self.data.active.len()
|
self.data.active.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text(&mut self, id: &impl IdLike<TextEdit>) -> 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) {
|
pub fn debug_layers(&self) {
|
||||||
for ((idx, depth), primitives) in self.data.layers.iter_depth() {
|
for ((idx, depth), primitives) in self.data.layers.iter_depth() {
|
||||||
let indent = " ".repeat(depth * 2);
|
let indent = " ".repeat(depth * 2);
|
||||||
@@ -178,7 +160,7 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_region<W>(&self, id: &impl IdLike<W>) -> Option<PixelRegion> {
|
pub fn window_region(&self, id: &impl IdLike) -> Option<PixelRegion> {
|
||||||
let region = self.data.active.get(&id.id())?.region;
|
let region = self.data.active.get(&id.id())?.region;
|
||||||
Some(region.to_px(self.data.output_size))
|
Some(region.to_px(self.data.output_size))
|
||||||
}
|
}
|
||||||
@@ -191,17 +173,16 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> Index<&WidgetId<W>> for Ui {
|
impl<I: IdLike> Index<&I> for Ui {
|
||||||
type Output = W;
|
type Output = I::Widget;
|
||||||
|
|
||||||
fn index(&self, id: &WidgetId<W>) -> &Self::Output {
|
fn index(&self, id: &I) -> &Self::Output {
|
||||||
self.get(id).unwrap()
|
self.get(id).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> IndexMut<&WidgetId<W>> for Ui {
|
impl<I: IdLike> IndexMut<&I> for Ui {
|
||||||
fn index_mut(&mut self, id: &WidgetId<W>) -> &mut Self::Output {
|
fn index_mut(&mut self, id: &I) -> &mut Self::Output {
|
||||||
self.updates.insert(id.id);
|
|
||||||
self.get_mut(id).unwrap()
|
self.get_mut(id).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,7 +203,6 @@ impl Default for Ui {
|
|||||||
Self {
|
Self {
|
||||||
data: PainterData::default(),
|
data: PainterData::default(),
|
||||||
root: Default::default(),
|
root: Default::default(),
|
||||||
updates: Default::default(),
|
|
||||||
full_redraw: false,
|
full_redraw: false,
|
||||||
send,
|
send,
|
||||||
recv,
|
recv,
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::{any::TypeId, marker::PhantomData, sync::mpsc::Sender};
|
use std::{any::TypeId, marker::PhantomData, sync::mpsc::Sender};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
layout::{Ui, WidgetLike},
|
layout::{Ui, Widget},
|
||||||
util::{Id, RefCounter},
|
util::{Id, RefCounter},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ impl<W> Clone for WidgetId<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<W> WidgetId<W> {
|
impl<W> WidgetId<W> {
|
||||||
pub(super) fn new(id: Id, ty: TypeId, send: Sender<Id>) -> Self {
|
pub(crate) fn new(id: Id, ty: TypeId, send: Sender<Id>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ty,
|
ty,
|
||||||
id,
|
id,
|
||||||
@@ -77,7 +77,7 @@ impl<W> WidgetId<W> {
|
|||||||
unsafe { std::mem::transmute(self) }
|
unsafe { std::mem::transmute(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn key(&self) -> Id {
|
pub fn id(&self) -> Id {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,26 +108,6 @@ impl<W> WidgetId<W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> WeakWidgetId<W> {
|
|
||||||
/// should guarantee that widget is still valid to prevent indexing failures
|
|
||||||
pub(crate) fn strong(&self) -> WidgetId<W> {
|
|
||||||
let Self {
|
|
||||||
ty,
|
|
||||||
id,
|
|
||||||
ref counter,
|
|
||||||
ref send,
|
|
||||||
_pd,
|
|
||||||
} = *self;
|
|
||||||
WidgetId {
|
|
||||||
ty,
|
|
||||||
id,
|
|
||||||
counter: counter.clone(),
|
|
||||||
send: send.clone(),
|
|
||||||
_pd,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W> Drop for WidgetId<W> {
|
impl<W> Drop for WidgetId<W> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.counter.drop() {
|
if self.counter.drop() {
|
||||||
@@ -136,29 +116,12 @@ impl<W> Drop for WidgetId<W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IdTag;
|
|
||||||
pub struct IdFnTag;
|
|
||||||
|
|
||||||
pub trait WidgetIdFn<W>: FnOnce(&mut Ui) -> WidgetId<W> {}
|
pub trait WidgetIdFn<W>: FnOnce(&mut Ui) -> WidgetId<W> {}
|
||||||
impl<W, F: FnOnce(&mut Ui) -> WidgetId<W>> WidgetIdFn<W> for F {}
|
impl<W, F: FnOnce(&mut Ui) -> WidgetId<W>> WidgetIdFn<W> for F {}
|
||||||
|
|
||||||
pub trait WidgetRet: FnOnce(&mut Ui) -> WidgetId<AnyWidget> {}
|
pub trait WidgetRet: FnOnce(&mut Ui) -> WidgetId<AnyWidget> {}
|
||||||
impl<F: FnOnce(&mut Ui) -> WidgetId<AnyWidget>> WidgetRet for F {}
|
impl<F: FnOnce(&mut Ui) -> WidgetId<AnyWidget>> WidgetRet for F {}
|
||||||
|
|
||||||
impl<W: 'static> WidgetLike<IdTag> for WidgetId<W> {
|
|
||||||
type Widget = W;
|
|
||||||
fn add(self, _: &mut Ui) -> WidgetId<W> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: 'static, F: FnOnce(&mut Ui) -> WidgetId<W>> WidgetLike<IdFnTag> for F {
|
|
||||||
type Widget = W;
|
|
||||||
fn add(self, ui: &mut Ui) -> WidgetId<W> {
|
|
||||||
self(ui)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WidgetIdLike<W> {
|
pub trait WidgetIdLike<W> {
|
||||||
fn id(self, send: &Sender<Id>) -> WidgetId<W>;
|
fn id(self, send: &Sender<Id>) -> WidgetId<W>;
|
||||||
}
|
}
|
||||||
@@ -169,11 +132,20 @@ impl<W> WidgetIdLike<W> for &WidgetId<W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IdLike<W> {
|
pub trait IdLike {
|
||||||
|
type Widget: Widget + 'static;
|
||||||
fn id(&self) -> Id;
|
fn id(&self) -> Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> IdLike<W> for WidgetId<W> {
|
impl<W: Widget> IdLike for WidgetId<W> {
|
||||||
|
type Widget = W;
|
||||||
|
fn id(&self) -> Id {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Widget> IdLike for WeakWidgetId<W> {
|
||||||
|
type Widget = W;
|
||||||
fn id(&self) -> Id {
|
fn id(&self) -> Id {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,4 @@
|
|||||||
use crate::{
|
use super::*;
|
||||||
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;
|
|
||||||
|
|
||||||
pub trait WidgetLike<Tag> {
|
pub trait WidgetLike<Tag> {
|
||||||
type Widget: 'static;
|
type Widget: 'static;
|
||||||
@@ -48,50 +24,8 @@ pub trait WidgetLike<Tag> {
|
|||||||
{
|
{
|
||||||
ui.set_root(self);
|
ui.set_root(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_ptr(self, ptr: &WidgetId<WidgetPtr>, 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<W: Widget>: FnOnce(&mut Ui) -> W {}
|
|
||||||
impl<W: Widget, F: FnOnce(&mut Ui) -> W> WidgetFn<W> for F {}
|
|
||||||
|
|
||||||
impl<W: Widget, F: FnOnce(&mut Ui) -> W> WidgetLike<FnTag> for F {
|
|
||||||
type Widget = W;
|
|
||||||
fn add(self, ui: &mut Ui) -> WidgetId<W> {
|
|
||||||
self(ui).add(ui)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: Widget> WidgetLike<WidgetTag> for W {
|
|
||||||
type Widget = W;
|
|
||||||
fn add(self, ui: &mut Ui) -> WidgetId<W> {
|
|
||||||
ui.add_widget(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WidgetArr<const LEN: usize, Ws> {
|
|
||||||
pub arr: [WidgetId; LEN],
|
|
||||||
_pd: PhantomData<Ws>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const LEN: usize, Ws> WidgetArr<LEN, Ws> {
|
|
||||||
pub fn new(arr: [WidgetId; LEN]) -> Self {
|
|
||||||
Self {
|
|
||||||
arr,
|
|
||||||
_pd: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ArrTag;
|
|
||||||
pub trait WidgetArrLike<const LEN: usize, Tag> {
|
pub trait WidgetArrLike<const LEN: usize, Tag> {
|
||||||
type Ws;
|
type Ws;
|
||||||
fn ui(self, ui: &mut Ui) -> WidgetArr<LEN, Self::Ws>;
|
fn ui(self, ui: &mut Ui) -> WidgetArr<LEN, Self::Ws>;
|
||||||
@@ -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!(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!(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);
|
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<WidgetId>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WidgetOption for () {
|
|
||||||
fn get(self, _: &mut Ui) -> Option<WidgetId> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F: FnOnce(&mut Ui) -> Option<WidgetId>> WidgetOption for F {
|
|
||||||
fn get(self, ui: &mut Ui) -> Option<WidgetId> {
|
|
||||||
self(ui)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<W: Widget>: FnOnce(&mut Ui) -> W {}
|
||||||
|
impl<W: Widget, F: FnOnce(&mut Ui) -> W> WidgetFn<W> for F {}
|
||||||
|
|
||||||
|
pub struct WidgetArr<const LEN: usize, Ws> {
|
||||||
|
pub arr: [WidgetId; LEN],
|
||||||
|
_pd: PhantomData<Ws>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize, Ws> WidgetArr<LEN, Ws> {
|
||||||
|
pub fn new(arr: [WidgetId; LEN]) -> Self {
|
||||||
|
Self {
|
||||||
|
arr,
|
||||||
|
_pd: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WidgetOption {
|
||||||
|
fn get(self, ui: &mut Ui) -> Option<WidgetId>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetOption for () {
|
||||||
|
fn get(self, _: &mut Ui) -> Option<WidgetId> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: FnOnce(&mut Ui) -> Option<WidgetId>> WidgetOption for F {
|
||||||
|
fn get(self, ui: &mut Ui) -> Option<WidgetId> {
|
||||||
|
self(ui)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct ArrTag;
|
||||||
|
|
||||||
|
pub struct WidgetTag;
|
||||||
|
impl<W: Widget> WidgetLike<WidgetTag> for W {
|
||||||
|
type Widget = W;
|
||||||
|
fn add(self, ui: &mut Ui) -> WidgetId<W> {
|
||||||
|
ui.add_widget(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FnTag;
|
||||||
|
impl<W: Widget, F: FnOnce(&mut Ui) -> W> WidgetLike<FnTag> for F {
|
||||||
|
type Widget = W;
|
||||||
|
fn add(self, ui: &mut Ui) -> WidgetId<W> {
|
||||||
|
self(ui).add(ui)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IdTag;
|
||||||
|
impl<W: 'static> WidgetLike<IdTag> for WidgetId<W> {
|
||||||
|
type Widget = W;
|
||||||
|
fn add(self, _: &mut Ui) -> WidgetId<W> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IdFnTag;
|
||||||
|
impl<W: 'static, F: FnOnce(&mut Ui) -> WidgetId<W>> WidgetLike<IdFnTag> for F {
|
||||||
|
type Widget = W;
|
||||||
|
fn add(self, ui: &mut Ui) -> WidgetId<W> {
|
||||||
|
self(ui)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
layout::{IdLike, Widget},
|
layout::{IdLike, Widget},
|
||||||
util::{DynBorrower, HashMap, Id, IdTracker},
|
util::{DynBorrower, HashMap, HashSet, Id, IdTracker},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Widgets {
|
pub struct Widgets {
|
||||||
|
pub updates: HashSet<Id>,
|
||||||
ids: IdTracker,
|
ids: IdTracker,
|
||||||
map: HashMap<Id, WidgetData>,
|
map: HashMap<Id, WidgetData>,
|
||||||
}
|
}
|
||||||
@@ -17,11 +18,8 @@ pub struct WidgetData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widgets {
|
impl Widgets {
|
||||||
pub fn new() -> Self {
|
pub fn has_updates(&self) -> bool {
|
||||||
Self {
|
!self.updates.is_empty()
|
||||||
ids: IdTracker::default(),
|
|
||||||
map: HashMap::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_dyn(&self, id: Id) -> Option<&dyn Widget> {
|
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> {
|
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())
|
Some(self.map.get_mut(&id)?.widget.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,11 +46,11 @@ impl Widgets {
|
|||||||
WidgetWrapper::new(data.widget.as_mut(), &mut data.borrowed)
|
WidgetWrapper::new(data.widget.as_mut(), &mut data.borrowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<W: Widget>(&self, id: &impl IdLike<W>) -> Option<&W> {
|
pub fn get<I: IdLike>(&self, id: &I) -> Option<&I::Widget> {
|
||||||
self.get_dyn(id.id())?.as_any().downcast_ref()
|
self.get_dyn(id.id())?.as_any().downcast_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut<W: Widget>(&mut self, id: &impl IdLike<W>) -> Option<&mut W> {
|
pub fn get_mut<I: IdLike>(&mut self, id: &I) -> Option<&mut I::Widget> {
|
||||||
self.get_dyn_mut(id.id())?.as_any_mut().downcast_mut()
|
self.get_dyn_mut(id.id())?.as_any_mut().downcast_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -4,13 +4,15 @@ mod change;
|
|||||||
mod id;
|
mod id;
|
||||||
mod math;
|
mod math;
|
||||||
mod refcount;
|
mod refcount;
|
||||||
|
mod vec2;
|
||||||
|
|
||||||
pub(crate) use arena::*;
|
pub use arena::*;
|
||||||
pub(crate) use borrow::*;
|
pub use borrow::*;
|
||||||
pub use change::*;
|
pub use change::*;
|
||||||
pub(crate) use id::*;
|
pub use id::*;
|
||||||
pub(crate) use math::*;
|
pub use math::*;
|
||||||
pub(crate) use refcount::*;
|
pub use refcount::*;
|
||||||
|
pub use vec2::*;
|
||||||
|
|
||||||
pub type HashMap<K, V> = fxhash::FxHashMap<K, V>;
|
pub type HashMap<K, V> = fxhash::FxHashMap<K, V>;
|
||||||
pub type HashSet<K> = fxhash::FxHashSet<K>;
|
pub type HashSet<K> = fxhash::FxHashSet<K>;
|
||||||
@@ -22,6 +22,12 @@ impl RefCounter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for RefCounter {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for RefCounter {
|
impl Clone for RefCounter {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
self.0.fetch_add(1, Ordering::Release);
|
self.0.fetch_add(1, Ordering::Release);
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
use crate::{
|
use crate::util::{DivOr, impl_op};
|
||||||
layout::UiNum,
|
use std::{hash::Hash, ops::*};
|
||||||
util::{DivOr, impl_op},
|
|
||||||
};
|
|
||||||
use std::{hash::Hash, marker::Destruct, ops::*};
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, PartialEq, Default, bytemuck::Pod, bytemuck::Zeroable)]
|
#[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 {
|
impl Vec2 {
|
||||||
pub const ZERO: Self = Self::new(0.0, 0.0);
|
pub const ZERO: Self = Self::new(0.0, 0.0);
|
||||||
pub const ONE: Self = Self::new(1.0, 1.0);
|
pub const ONE: Self = Self::new(1.0, 1.0);
|
||||||
@@ -68,15 +61,6 @@ impl Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: const UiNum + Copy> const From<T> 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
|
// 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!(impl Add for Vec2: add x y);
|
||||||
impl_op!(Vec2 Sub sub; x y);
|
impl_op!(Vec2 Sub sub; x y);
|
||||||
@@ -102,18 +86,6 @@ impl Neg for Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: const UiNum, U: const UiNum> 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 {
|
impl std::fmt::Debug for Vec2 {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "({}, {})", self.x, self.y)
|
write!(f, "({}, {})", self.x, self.y)
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
use iris::{prelude::*, winit::*};
|
use iris::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
DefaultApp::<State>::run();
|
DefaultApp::<State>::run();
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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<Attribute>,
|
||||||
|
vis: Visibility,
|
||||||
|
name: Ident,
|
||||||
|
fns: Vec<InputFn>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InputFn {
|
||||||
|
sig: Signature,
|
||||||
|
body: Block,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for Input {
|
||||||
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
|
let attrs = input.call(Attribute::parse_outer)?;
|
||||||
|
let vis = input.parse()?;
|
||||||
|
input.parse::<Token![trait]>()?;
|
||||||
|
let name = input.parse()?;
|
||||||
|
input.parse::<Token![;]>()?;
|
||||||
|
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<WL: WidgetLike<Tag>, Tag> {
|
||||||
|
#(#sigs;)*
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
trai.attrs = attrs;
|
||||||
|
|
||||||
|
TokenStream::from(quote! {
|
||||||
|
#trai
|
||||||
|
|
||||||
|
impl<WL: WidgetLike<Tag>, Tag> #name<WL, Tag> for WL {
|
||||||
|
#(#impls)*
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
use cosmic_text::Family;
|
use cosmic_text::Family;
|
||||||
use iris::{
|
use iris::prelude::*;
|
||||||
prelude::*,
|
|
||||||
winit::{attr::Selectable, event::Submit, *},
|
|
||||||
};
|
|
||||||
use len_fns::*;
|
use len_fns::*;
|
||||||
use winit::event::WindowEvent;
|
use winit::event::WindowEvent;
|
||||||
|
|
||||||
@@ -110,7 +107,7 @@ impl DefaultAppState for Client {
|
|||||||
.size(30)
|
.size(30)
|
||||||
.attr::<Selectable>(())
|
.attr::<Selectable>(())
|
||||||
.on(Submit, move |ctx| {
|
.on(Submit, move |ctx| {
|
||||||
let content = ctx.ui.text(ctx.id).take();
|
let content = ctx.id.edit(ctx.ui).take();
|
||||||
let text = wtext(content)
|
let text = wtext(content)
|
||||||
.editable(false)
|
.editable(false)
|
||||||
.size(30)
|
.size(30)
|
||||||
|
|||||||
File renamed without changes.
@@ -1,10 +1,10 @@
|
|||||||
use crate::{prelude::*, winit::UiState};
|
use crate::{default::UiState, prelude::*};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use winit::dpi::{LogicalPosition, LogicalSize};
|
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||||
|
|
||||||
pub struct Selector;
|
pub struct Selector;
|
||||||
|
|
||||||
impl<W: 'static> WidgetAttr<W> for Selector {
|
impl<W: 'static + Widget> WidgetAttr<W> for Selector {
|
||||||
type Input = WidgetId<TextEdit>;
|
type Input = WidgetId<TextEdit>;
|
||||||
|
|
||||||
fn run(ui: &mut Ui, container: &WidgetId<W>, id: Self::Input) {
|
fn run(ui: &mut Ui, container: &WidgetId<W>, id: Self::Input) {
|
||||||
@@ -42,7 +42,7 @@ fn select(ui: &mut Ui, id: WidgetId<TextEdit>, state: &mut UiState, data: Cursor
|
|||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let recent = (now - state.last_click) < Duration::from_millis(300);
|
let recent = (now - state.last_click) < Duration::from_millis(300);
|
||||||
state.last_click = now;
|
state.last_click = now;
|
||||||
ui.text(&id)
|
id.edit(ui)
|
||||||
.select(data.cursor, data.size, data.sense.is_dragging(), recent);
|
.select(data.cursor, data.size, data.sense.is_dragging(), recent);
|
||||||
if let Some(region) = ui.window_region(&id) {
|
if let Some(region) = ui.window_region(&id) {
|
||||||
state.window.set_ime_allowed(true);
|
state.window.set_ime_allowed(true);
|
||||||
@@ -2,14 +2,8 @@ use crate::layout::DefaultEvent;
|
|||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Clone)]
|
#[derive(Eq, PartialEq, Hash, Clone)]
|
||||||
pub struct Submit;
|
pub struct Submit;
|
||||||
|
impl DefaultEvent for Submit {}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Clone)]
|
#[derive(Eq, PartialEq, Hash, Clone)]
|
||||||
pub struct Edited;
|
pub struct Edited;
|
||||||
|
impl DefaultEvent for Edited {}
|
||||||
impl DefaultEvent for Submit {
|
|
||||||
type Data = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DefaultEvent for Edited {
|
|
||||||
type Data = ();
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
use crate::{
|
use crate::prelude::*;
|
||||||
core::{CursorState, Modifiers},
|
|
||||||
layout::Vec2,
|
|
||||||
winit::UiState,
|
|
||||||
};
|
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{MouseButton, MouseScrollDelta, WindowEvent},
|
event::{MouseButton, MouseScrollDelta, WindowEvent},
|
||||||
keyboard::{Key, NamedKey},
|
keyboard::{Key, NamedKey},
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::winit::event::{Edited, Submit};
|
|
||||||
use crate::winit::{input::Input, render::UiRenderer};
|
|
||||||
use arboard::Clipboard;
|
use arboard::Clipboard;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@@ -9,12 +7,16 @@ use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
|
|||||||
use winit::window::{Window, WindowAttributes};
|
use winit::window::{Window, WindowAttributes};
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
pub mod attr;
|
mod attr;
|
||||||
pub mod event;
|
mod event;
|
||||||
pub mod input;
|
mod input;
|
||||||
pub mod render;
|
mod render;
|
||||||
|
|
||||||
pub use app::*;
|
pub use app::*;
|
||||||
|
pub use attr::*;
|
||||||
|
pub use event::*;
|
||||||
|
pub use input::*;
|
||||||
|
pub use render::*;
|
||||||
|
|
||||||
pub type Proxy<Event> = EventLoopProxy<Event>;
|
pub type Proxy<Event> = EventLoopProxy<Event>;
|
||||||
pub type DefaultApp<Data> = App<DefaultState<Data>>;
|
pub type DefaultApp<Data> = App<DefaultState<Data>>;
|
||||||
@@ -105,7 +107,7 @@ impl<State: DefaultAppState> AppState for DefaultState<State> {
|
|||||||
if old != ui_state.focus
|
if old != ui_state.focus
|
||||||
&& let Some(old) = old
|
&& let Some(old) = old
|
||||||
{
|
{
|
||||||
ui.text(&old).deselect();
|
old.edit(ui).deselect();
|
||||||
}
|
}
|
||||||
match &event {
|
match &event {
|
||||||
WindowEvent::CloseRequested => event_loop.exit(),
|
WindowEvent::CloseRequested => event_loop.exit(),
|
||||||
@@ -123,7 +125,7 @@ impl<State: DefaultAppState> AppState for DefaultState<State> {
|
|||||||
&& event.state.is_pressed()
|
&& event.state.is_pressed()
|
||||||
{
|
{
|
||||||
let sel = &sel.clone();
|
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) {
|
match text.apply_event(event, &ui_state.input.modifiers) {
|
||||||
TextInputResult::Unfocus => {
|
TextInputResult::Unfocus => {
|
||||||
ui_state.focus = None;
|
ui_state.focus = None;
|
||||||
@@ -152,7 +154,7 @@ impl<State: DefaultAppState> AppState for DefaultState<State> {
|
|||||||
}
|
}
|
||||||
WindowEvent::Ime(ime) => {
|
WindowEvent::Ime(ime) => {
|
||||||
if let Some(sel) = &ui_state.focus {
|
if let Some(sel) = &ui_state.focus {
|
||||||
let mut text = ui.text(sel);
|
let mut text = sel.edit(ui);
|
||||||
match ime {
|
match ime {
|
||||||
Ime::Enabled | Ime::Disabled => (),
|
Ime::Enabled | Ime::Disabled => (),
|
||||||
Ime::Preedit(content, _pos) => {
|
Ime::Preedit(content, _pos) => {
|
||||||
File renamed without changes.
@@ -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<W, Tag, Ctx: 'static> {
|
||||||
|
fn on<E: Event>(
|
||||||
|
self,
|
||||||
|
event: E,
|
||||||
|
f: impl WidgetEventFn<Ctx, E::Data, W>,
|
||||||
|
) -> impl WidgetIdFn<W> + EventableCtx<W, IdFnTag, Ctx>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<WL: WidgetLike<Tag>, Tag> EventableCtx<WL::Widget, Tag, $ty> for WL {
|
||||||
|
fn on<E: Event>(
|
||||||
|
self,
|
||||||
|
event: E,
|
||||||
|
f: impl WidgetEventFn<$ty, E::Data, WL::Widget>,
|
||||||
|
) -> impl WidgetIdFn<WL::Widget> + EventableCtx<WL::Widget, IdFnTag, $ty> {
|
||||||
|
eventable::Eventable::on(self, event, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use local_event_trait::*;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub use event_ctx;
|
||||||
|
|
||||||
|
pub mod eventable {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub trait Eventable<W, Tag> {
|
||||||
|
fn on<E: Event, Ctx: 'static>(
|
||||||
|
self,
|
||||||
|
event: E,
|
||||||
|
f: impl WidgetEventFn<Ctx, E::Data, W>,
|
||||||
|
) -> impl WidgetIdFn<W> + Eventable<W, IdFnTag>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<WL: WidgetLike<Tag>, Tag> Eventable<WL::Widget, Tag> for WL {
|
||||||
|
fn on<E: Event, Ctx: 'static>(
|
||||||
|
self,
|
||||||
|
event: E,
|
||||||
|
f: impl WidgetEventFn<Ctx, E::Data, WL::Widget>,
|
||||||
|
) -> impl WidgetIdFn<WL::Widget> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
//! tree structure for masking
|
|
||||||
|
|
||||||
use crate::layout::UiRegion;
|
|
||||||
|
|
||||||
pub struct Masks {
|
|
||||||
data: Vec<MaskNode>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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) {}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+15
-16
@@ -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(unboxed_closures)]
|
||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
#![feature(const_cmp)]
|
|
||||||
#![feature(const_destruct)]
|
|
||||||
#![feature(portable_simd)]
|
|
||||||
#![feature(gen_blocks)]
|
#![feature(gen_blocks)]
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
|
|
||||||
pub mod core;
|
mod default;
|
||||||
pub mod layout;
|
mod event;
|
||||||
pub mod render;
|
mod widget;
|
||||||
pub mod util;
|
|
||||||
pub mod winit;
|
pub use iris_core::*;
|
||||||
|
pub use iris_macro::*;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::core::*;
|
use super::*;
|
||||||
pub use crate::layout::*;
|
pub use default::*;
|
||||||
pub use crate::render::*;
|
pub use event::*;
|
||||||
|
pub use iris_macro::*;
|
||||||
|
pub use layout::*;
|
||||||
|
pub use render::*;
|
||||||
|
pub use widget::*;
|
||||||
|
|
||||||
|
pub use super::util::Vec2;
|
||||||
}
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,8 +6,8 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
layout::{UiModule, UiRegion, Vec2},
|
layout::{UiModule, UiRegion},
|
||||||
util::{HashMap, Id},
|
util::{HashMap, Id, Vec2},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
@@ -166,8 +166,12 @@ impl<Ctx> CursorModule<Ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ui {
|
pub trait SensorUi {
|
||||||
pub fn run_sensors<Ctx: 'static>(
|
fn run_sensors<Ctx: 'static>(&mut self, ctx: &mut Ctx, cursor: &CursorState, window_size: Vec2);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SensorUi for Ui {
|
||||||
|
fn run_sensors<Ctx: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
cursor: &CursorState,
|
cursor: &CursorState,
|
||||||
@@ -205,7 +209,11 @@ impl<Ctx: 'static> CursorModule<Ctx> {
|
|||||||
scroll_delta: cursor.scroll_delta,
|
scroll_delta: cursor.scroll_delta,
|
||||||
sense,
|
sense,
|
||||||
};
|
};
|
||||||
(sensor.f)(EventCtx { ui, state: ctx, data });
|
(sensor.f)(EventCtx {
|
||||||
|
ui,
|
||||||
|
state: ctx,
|
||||||
|
data,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File renamed without changes.
@@ -610,3 +610,16 @@ impl DerefMut for TextEdit {
|
|||||||
&mut self.view
|
&mut self.view
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait TextEditable {
|
||||||
|
fn edit<'a>(&self, ui: &'a mut Ui) -> TextEditCtx<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: IdLike<Widget = TextEdit>> 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user