I love control flow
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
name = "iris"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
default-run = "test"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
@@ -1,3 +1,4 @@
|
||||
use crate::Client;
|
||||
use iris::{
|
||||
core::{CursorState, Modifiers},
|
||||
layout::Vec2,
|
||||
@@ -7,8 +8,6 @@ use winit::{
|
||||
keyboard::{Key, NamedKey},
|
||||
};
|
||||
|
||||
use crate::testing::Client;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Input {
|
||||
cursor: CursorState,
|
||||
@@ -1,20 +1,18 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use app::App;
|
||||
use arboard::Clipboard;
|
||||
use cosmic_text::Family;
|
||||
use input::Input;
|
||||
use iris::prelude::*;
|
||||
use render::Renderer;
|
||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||
|
||||
use crate::testing::input::Input;
|
||||
use len_fns::*;
|
||||
use render::Renderer;
|
||||
use std::sync::Arc;
|
||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||
|
||||
mod app;
|
||||
mod input;
|
||||
mod render;
|
||||
|
||||
pub fn main() {
|
||||
fn main() {
|
||||
App::run();
|
||||
}
|
||||
|
||||
@@ -100,8 +98,6 @@ impl Client {
|
||||
.stack()
|
||||
.add_static(&mut ui);
|
||||
|
||||
let main = pad_test.pad(10).add_static(&mut ui);
|
||||
|
||||
let btext = |content| text(content).size(30);
|
||||
|
||||
let text_test = (
|
||||
@@ -176,6 +172,8 @@ impl Client {
|
||||
.span(Dir::DOWN)
|
||||
.add_static(&mut ui);
|
||||
|
||||
let main = pad_test.pad(10).add_static(&mut ui);
|
||||
|
||||
let switch_button = |color, to, label| {
|
||||
let rect = rect(color)
|
||||
.id_on(CursorSense::click(), move |id, ui: &mut Ui, _| {
|
||||
@@ -1,6 +1,7 @@
|
||||
mod align;
|
||||
mod offset;
|
||||
mod pad;
|
||||
mod scroll;
|
||||
mod sized;
|
||||
mod span;
|
||||
mod stack;
|
||||
|
||||
39
src/core/position/scroll.rs
Normal file
39
src/core/position/scroll.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct Scroll {
|
||||
inner: WidgetId,
|
||||
axis: Axis,
|
||||
snap_end: bool,
|
||||
amt: f32,
|
||||
draw_len: f32,
|
||||
}
|
||||
|
||||
impl Widget for Scroll {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
let output_len = painter.output_size().axis(self.axis);
|
||||
let container_len = painter.region().axis(self.axis).len();
|
||||
let content_len = painter
|
||||
.len_axis(&self.inner, self.axis)
|
||||
.apply_rest()
|
||||
.within_len(container_len)
|
||||
.to_abs(output_len);
|
||||
let container_len = container_len.to_abs(output_len);
|
||||
self.draw_len = content_len;
|
||||
// let region = UiRegion::FULL.offset(self.amt);
|
||||
// painter.widget_within(&self.inner, region);
|
||||
}
|
||||
|
||||
fn desired_width(&mut self, _: &mut SizeCtx) -> Len {
|
||||
Len::default()
|
||||
}
|
||||
|
||||
fn desired_height(&mut self, _: &mut SizeCtx) -> Len {
|
||||
Len::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Scroll {
|
||||
pub fn scroll(&mut self, amt: f32) {
|
||||
self.amt += amt;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@ impl Widget for Span {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
let total = self.len_sum(&mut painter.size_ctx());
|
||||
let mut start = UiScalar::rel_min();
|
||||
if painter.label() == "fricker" {
|
||||
println!("redraw");
|
||||
}
|
||||
for child in &self.children {
|
||||
let mut span = UiSpan::FULL;
|
||||
span.start = start;
|
||||
@@ -88,7 +91,10 @@ impl Span {
|
||||
}
|
||||
|
||||
fn desired_ortho(&mut self, ctx: &mut SizeCtx) -> Len {
|
||||
// this is an awful hack to get text wrapping to work properly when in a downward span
|
||||
// this is a weird hack to get text wrapping to work properly when in a downward span
|
||||
// the correct solution here is to add a function to widget that lets them
|
||||
// request that ctx.outer has an axis "resolved" before checking the other,
|
||||
// and panicking or warning if two request opposite axis (unsolvable in that case)
|
||||
let outer = ctx.outer.axis(self.dir.axis);
|
||||
if self.dir.axis == Axis::X {
|
||||
// so....... this literally copies draw so that the lengths are correctly set in the
|
||||
|
||||
@@ -26,7 +26,6 @@ impl TextEdit {
|
||||
.lines
|
||||
.iter()
|
||||
.map(|l| l.text())
|
||||
// why is this needed?? what??
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
@@ -44,9 +43,7 @@ impl Widget for TextEdit {
|
||||
let size = vec2(1, self.attrs.line_height);
|
||||
painter.primitive_within(
|
||||
RectPrimitive::color(Color::WHITE),
|
||||
size.align(Align::TOP_LEFT)
|
||||
.offset(offset)
|
||||
.within(®ion),
|
||||
size.align(Align::TOP_LEFT).offset(offset).within(®ion),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,12 @@ impl<Nx: UiNum, Ny: UiNum> From<(Nx, Ny)> for Size {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Len> for Size {
|
||||
fn from(value: Len) -> Self {
|
||||
Self { x: value, y: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl Size {
|
||||
pub const ZERO: Self = Self {
|
||||
x: Len::ZERO,
|
||||
@@ -171,10 +177,10 @@ impl std::fmt::Display for Len {
|
||||
write!(f, "{} abs;", self.abs)?;
|
||||
}
|
||||
if self.rel != 0.0 {
|
||||
write!(f, "{} rel;", self.abs)?;
|
||||
write!(f, "{} rel;", self.rel)?;
|
||||
}
|
||||
if self.rest != 0.0 {
|
||||
write!(f, "{} leftover;", self.abs)?;
|
||||
write!(f, "{} rest;", self.rest)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -78,7 +78,10 @@ impl UiVec2 {
|
||||
}
|
||||
|
||||
pub fn to_abs(&self, rel: Vec2) -> Vec2 {
|
||||
self.get_rel() * rel + self.get_abs()
|
||||
Vec2 {
|
||||
x: self.x.to_abs(rel.x),
|
||||
y: self.y.to_abs(rel.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const FULL_SIZE: Self = Self::rel(Vec2::ONE);
|
||||
@@ -231,6 +234,10 @@ impl UiScalar {
|
||||
pub const fn to(&self, end: Self) -> UiSpan {
|
||||
UiSpan { start: *self, end }
|
||||
}
|
||||
|
||||
pub const fn to_abs(&self, rel: f32) -> f32 {
|
||||
self.rel * rel + self.abs
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@@ -323,6 +330,14 @@ impl UiRegion {
|
||||
y: self.y.outside(&parent.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn axis(&mut self, axis: Axis) -> &UiSpan {
|
||||
match axis {
|
||||
Axis::X => &self.x,
|
||||
Axis::Y => &self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn axis_mut(&mut self, axis: Axis) -> &mut UiSpan {
|
||||
match axis {
|
||||
Axis::X => &mut self.x,
|
||||
|
||||
@@ -29,19 +29,20 @@ pub struct PainterCtx<'a> {
|
||||
pub textures: &'a mut Textures,
|
||||
pub masks: &'a mut TrackedArena<Mask, u32>,
|
||||
pub text: &'a mut TextData,
|
||||
pub screen_size: Vec2,
|
||||
pub output_size: Vec2,
|
||||
pub modules: &'a mut Modules,
|
||||
pub cache_width: HashMap<Id, (UiVec2, Len)>,
|
||||
pub cache_height: HashMap<Id, (UiVec2, Len)>,
|
||||
draw_started: HashSet<Id>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct ResizeRef {
|
||||
x: Option<(Id, (UiVec2, Len))>,
|
||||
y: Option<(Id, (UiVec2, Len))>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WidgetInstance {
|
||||
pub id: Id,
|
||||
pub region: UiRegion,
|
||||
@@ -75,7 +76,7 @@ impl<'a> PainterCtx<'a> {
|
||||
layers: &mut data.layers,
|
||||
textures: &mut data.textures,
|
||||
text: &mut data.text,
|
||||
screen_size: data.output_size,
|
||||
output_size: data.output_size,
|
||||
modules: &mut data.modules,
|
||||
masks: &mut data.masks,
|
||||
cache_width: Default::default(),
|
||||
@@ -91,9 +92,16 @@ impl<'a> PainterCtx<'a> {
|
||||
let Some(active) = self.active.get(&id) else {
|
||||
return;
|
||||
};
|
||||
let mut resize = active.resize;
|
||||
|
||||
// TODO: this is stupid having 2 of these
|
||||
if let Some((rid, (outer, old_desired))) = active.resize.x {
|
||||
let finish = |s: &mut Self, resize| {
|
||||
if let Some(active) = s.active.get_mut(&id) {
|
||||
active.resize = resize;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: this is stupid having 2 of these, don't ask me what the consequences are
|
||||
if let Some((rid, (outer, old_desired))) = &mut resize.x {
|
||||
let new_desired = SizeCtx {
|
||||
source: id,
|
||||
cache_width: &mut self.cache_width,
|
||||
@@ -101,25 +109,23 @@ impl<'a> PainterCtx<'a> {
|
||||
text: self.text,
|
||||
textures: self.textures,
|
||||
widgets: self.widgets,
|
||||
outer,
|
||||
output_size: self.screen_size,
|
||||
outer: *outer,
|
||||
output_size: self.output_size,
|
||||
checked_width: &mut Default::default(),
|
||||
checked_height: &mut Default::default(),
|
||||
id,
|
||||
}
|
||||
.width_inner(id);
|
||||
if new_desired != old_desired {
|
||||
self.redraw(rid);
|
||||
if new_desired != *old_desired {
|
||||
self.redraw(*rid);
|
||||
*old_desired = new_desired;
|
||||
if self.draw_started.contains(&id) {
|
||||
return;
|
||||
return finish(self, resize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(active) = self.active.get(&id) else {
|
||||
return;
|
||||
};
|
||||
if let Some((rid, (outer, old_desired))) = active.resize.y {
|
||||
if let Some((rid, (outer, old_desired))) = &mut resize.y {
|
||||
let new_desired = SizeCtx {
|
||||
source: id,
|
||||
cache_width: &mut self.cache_width,
|
||||
@@ -127,17 +133,18 @@ impl<'a> PainterCtx<'a> {
|
||||
text: self.text,
|
||||
textures: self.textures,
|
||||
widgets: self.widgets,
|
||||
outer,
|
||||
output_size: self.screen_size,
|
||||
outer: *outer,
|
||||
output_size: self.output_size,
|
||||
checked_width: &mut Default::default(),
|
||||
checked_height: &mut Default::default(),
|
||||
id,
|
||||
}
|
||||
.height_inner(id);
|
||||
if new_desired != old_desired {
|
||||
self.redraw(rid);
|
||||
if new_desired != *old_desired {
|
||||
self.redraw(*rid);
|
||||
*old_desired = new_desired;
|
||||
if self.draw_started.contains(&id) {
|
||||
return;
|
||||
return finish(self, resize);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,7 +161,7 @@ impl<'a> PainterCtx<'a> {
|
||||
active.mask,
|
||||
Some(active.children),
|
||||
);
|
||||
self.active.get_mut(&id).unwrap().resize = active.resize;
|
||||
finish(self, resize);
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, id: Id) {
|
||||
@@ -399,7 +406,7 @@ impl<'a, 'c> Painter<'a, 'c> {
|
||||
text: self.ctx.text,
|
||||
textures: self.ctx.textures,
|
||||
widgets: self.ctx.widgets,
|
||||
output_size: self.ctx.screen_size,
|
||||
output_size: self.ctx.output_size,
|
||||
checked_width: &mut self.children_width,
|
||||
checked_height: &mut self.children_height,
|
||||
cache_width: &mut self.ctx.cache_width,
|
||||
@@ -410,8 +417,12 @@ impl<'a, 'c> Painter<'a, 'c> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output_size(&self) -> Vec2 {
|
||||
self.ctx.output_size
|
||||
}
|
||||
|
||||
pub fn px_size(&mut self) -> Vec2 {
|
||||
self.region.size().to_abs(self.ctx.screen_size)
|
||||
self.region.size().to_abs(self.ctx.output_size)
|
||||
}
|
||||
|
||||
pub fn text_data(&mut self) -> &mut TextData {
|
||||
|
||||
@@ -7,7 +7,7 @@ use image::{DynamicImage, GenericImageView};
|
||||
|
||||
use crate::{layout::Vec2, render::TexturePrimitive, util::RefCounter};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextureHandle {
|
||||
inner: TexturePrimitive,
|
||||
size: Vec2,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
core::{TextEdit, TextEditCtx},
|
||||
layout::{
|
||||
IdLike, PainterCtx, PainterData, PixelRegion, StaticWidgetId, TextureHandle, Vec2, Widget,
|
||||
WidgetId, WidgetLike,
|
||||
WidgetId, WidgetInstance, WidgetLike,
|
||||
},
|
||||
util::{HashSet, Id},
|
||||
};
|
||||
@@ -184,20 +184,11 @@ impl Ui {
|
||||
Some(region.to_px(self.data.output_size))
|
||||
}
|
||||
|
||||
pub fn debug(&self, label: &str) {
|
||||
for (id, inst) in &self.data.active {
|
||||
let l = &self.data.widgets.data(id).unwrap().label;
|
||||
if l != label {
|
||||
continue;
|
||||
}
|
||||
println!("\"{label}\" {{");
|
||||
println!(" region: {}", inst.region);
|
||||
println!(
|
||||
" pixel region: {}",
|
||||
inst.region.to_px(self.data.output_size)
|
||||
);
|
||||
println!("}}");
|
||||
}
|
||||
pub fn debug(&self, label: &str) -> impl Iterator<Item = &WidgetInstance> {
|
||||
self.data.active.iter().filter_map(move |(id, inst)| {
|
||||
let l = &self.data.widgets.label(id);
|
||||
if *l == label { Some(inst) } else { None }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
mod testing;
|
||||
|
||||
fn main() {
|
||||
testing::main();
|
||||
}
|
||||
@@ -223,7 +223,7 @@ impl RectPrimitive {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TexturePrimitive {
|
||||
pub view_idx: u32,
|
||||
pub sampler_idx: u32,
|
||||
|
||||
@@ -26,6 +26,9 @@ impl<I: IdNum> IdTracker<I> {
|
||||
}
|
||||
|
||||
impl<I: IdNum> Id<I> {
|
||||
pub(crate) fn raw(id: I) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
pub fn idx(&self) -> usize {
|
||||
self.0.idx()
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::sync::{
|
||||
atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RefCounter(Arc<AtomicU32>);
|
||||
|
||||
impl RefCounter {
|
||||
|
||||
Reference in New Issue
Block a user