From 2cbf0fcab2ff1694770a3ca2d186dd700205cecc Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Wed, 29 Oct 2025 21:10:51 -0600 Subject: [PATCH] Finish constraint layout --- src/app/mod.rs | 26 ++- src/lib.rs | 1 - src/render/buffer.rs | 337 +-------------------------------- src/views/color_rect_view.rs | 43 +++-- src/views/constraint_layout.rs | 175 ++++------------- src/views/mod.rs | 32 +++- src/views/text_view.rs | 21 +- src/views/vertical_layout.rs | 8 +- 8 files changed, 124 insertions(+), 519 deletions(-) diff --git a/src/app/mod.rs b/src/app/mod.rs index 29aa1b1..3da75e1 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,27 +1,14 @@ mod cursors; -use std::time::Instant; - pub use cursors::{Cursor, set_cursor}; use wasm_bindgen::prelude::wasm_bindgen; use crate::{ - log, render::Renderer, views::{View, default_view}, }; -pub trait Activity { - fn new() -> Self - where - Self: Sized; - fn update(&mut self, dt: f32); - fn draw(&self, renderer: &mut Renderer, state: &AppState); - fn l_click(&mut self, renderer: &mut Renderer, state: &AppState); - fn mouse_move(&mut self, renderer: &mut Renderer, state: &AppState); -} - #[wasm_bindgen] pub struct App { // pub(crate) activities: Vec>, @@ -47,12 +34,18 @@ impl AppState { impl App { pub fn new(renderer: Renderer) -> Self { - App { + let (width, height) = (renderer.actual_width, renderer.actual_height); + + let mut this = App { root_view: Some(default_view()), renderer, // current_activity: Some(0), state: AppState::new(), - } + }; + + this.resize(width, height); + + this } pub fn draw(&mut self) { @@ -72,6 +65,9 @@ impl App { impl App { pub fn resize(&mut self, width: usize, height: usize) { self.renderer.resize(width, height); + if let Some(view) = &mut self.root_view { + view.resize(0., 0., width as f32, height as f32); + } self.draw(); } diff --git a/src/lib.rs b/src/lib.rs index b28e9cf..572308b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -// mod activities; mod app; mod fonts; mod render; diff --git a/src/render/buffer.rs b/src/render/buffer.rs index a20b76d..f75c8e7 100644 --- a/src/render/buffer.rs +++ b/src/render/buffer.rs @@ -1,9 +1,4 @@ -// use crate::console_log; -use crate::render::rand; - -// macro_rules! log { -// ($($t:tt)*) => (console_log(&format_args!($($t)*).to_string())) -// } +// use crate::render::rand; pub struct ImgBuffer { pub data: Vec, @@ -20,14 +15,14 @@ impl ImgBuffer { } } - pub fn randomize(&mut self, rand: &mut rand::Rnd) { - for pixel in self.data.chunks_mut(4) { - pixel[0] = rand.next_i32() as u8; - pixel[1] = pixel[0]; - pixel[2] = pixel[0]; - pixel[3] = 255; - } - } + // pub fn randomize(&mut self, rand: &mut rand::Rnd) { + // for pixel in self.data.chunks_mut(4) { + // pixel[0] = rand.next_i32() as u8; + // pixel[1] = pixel[0]; + // pixel[2] = pixel[0]; + // pixel[3] = 255; + // } + // } pub fn overlay_bitmap(&mut self, other: &Bitmap, xoffset: usize, yoffset: usize) { let length = self.data.len(); @@ -77,320 +72,6 @@ impl ImgBuffer { } } -// // use icy_sixel::{ -// // DiffusionMethod, MethodForLargest, MethodForRep, PixelFormat, Quality, sixel_string, -// // }; - -// pub struct Bitmap { -// pub data: Vec, -// pub width: usize, -// pub height: usize, -// } - -// impl Bitmap { -// pub fn new(width: usize, height: usize) -> Self { -// Self { -// data: vec![0; width * height], -// width, -// height, -// } -// } - -// pub fn from_data(data: Vec, width: usize, height: usize) -> Self { -// assert!(data.len() == width * height); -// Self { -// data, -// width, -// height, -// } -// } - -// pub fn overlay(&mut self, other: &Bitmap, xoffset: usize, yoffset: usize) { -// for y in 0..other.height { -// for x in 0..other.width { -// self.data[(y + yoffset as usize) * self.width + (x + xoffset as usize)] = -// other.data[y * other.width + x]; -// } -// } -// } - -// // /// Prints a 1 byte per pixel greyscale bitmap to Sixel format in console -// // pub fn print(&self) { -// // let mut bitmap_rgb888 = vec![0; self.width * self.height * 3]; - -// // for y in 0..self.height { -// // for x in 0..self.width { -// // let index = y * self.width + x; - -// // let pixel = self.data[index]; - -// // bitmap_rgb888[index * 3] = pixel; -// // bitmap_rgb888[index * 3 + 1] = pixel; -// // bitmap_rgb888[index * 3 + 2] = pixel; -// // } -// // } - -// // let sixel_data = sixel_string( -// // &bitmap_rgb888, -// // self.width as i32, -// // self.height as i32, -// // PixelFormat::RGB888, -// // DiffusionMethod::None, -// // MethodForLargest::Auto, -// // MethodForRep::Auto, -// // Quality::AUTO, -// // ) -// // .unwrap(); - -// // println!("{}", sixel_data); -// // } -// } - -// impl Bitmap { -// /// Sets a pixel value with bounds checking -// fn set_pixel(&mut self, x: usize, y: usize, value: u8) { -// if x < self.width && y < self.height { -// self.data[y * self.width + x] = value; -// } -// } - -// /// Gets a pixel value with bounds checking -// fn get_pixel(&self, x: usize, y: usize) -> u8 { -// if x < self.width && y < self.height { -// self.data[y * self.width + x] -// } else { -// 0 -// } -// } - -// /// Draws an antialiased line with arbitrary thickness -// pub fn draw_line( -// &mut self, -// x0: usize, -// y0: usize, -// x1: usize, -// y1: usize, -// thickness: f32, -// color: u8, -// ) { -// let x0 = x0 as f32; -// let y0 = y0 as f32; -// let x1 = x1 as f32; -// let y1 = y1 as f32; - -// let dx = x1 - x0; -// let dy = y1 - y0; -// let length = (dx * dx + dy * dy).sqrt(); - -// if length < 0.001 { -// // Handle degenerate case of zero-length line -// // self.draw_thick_point(x0 as usize, y0 as usize, thickness, color); -// return; -// } - -// // Unit vector perpendicular to the line -// // let perp_x = -dy / length; -// // let perp_y = dx / length; - -// // Half thickness for calculations -// let half_thickness = thickness * 0.5; - -// // Calculate bounding box with some padding for antialiasing -// let padding = (thickness * 0.5 + 1.0).ceil() as i32; -// let min_x = ((x0.min(x1) - padding as f32).floor() as i32).max(0) as usize; -// let max_x = -// ((x0.max(x1) + padding as f32).ceil() as i32).min(self.width as i32 - 1) as usize; -// let min_y = ((y0.min(y1) - padding as f32).floor() as i32).max(0) as usize; -// let max_y = -// ((y0.max(y1) + padding as f32).ceil() as i32).min(self.height as i32 - 1) as usize; - -// // For each pixel in the bounding box, calculate distance to line -// for y in min_y..=max_y { -// for x in min_x..=max_x { -// let px = x as f32; -// let py = y as f32; - -// // Calculate distance from point to line segment -// let distance = self.point_to_line_segment_distance(px, py, x0, y0, x1, y1); - -// // Calculate alpha based on distance and thickness -// let alpha = self.calculate_alpha(distance, half_thickness); - -// if alpha > 0.0 { -// self.blend_pixel(x, y, color, alpha); -// } -// } -// } -// } - -// /// Blends a pixel with the existing value using alpha blending -// fn blend_pixel(&mut self, x: usize, y: usize, color: u8, alpha: f32) { -// if x < self.width && y < self.height { -// let existing = self.get_pixel(x, y) as f32; -// let new_value = (existing * (1.0 - alpha) + color as f32 * alpha).round() as u8; -// self.set_pixel(x, y, new_value); -// } -// } - -// /// Calculates the shortest distance from a point to a line segment -// fn point_to_line_segment_distance( -// &self, -// px: f32, -// py: f32, -// x0: f32, -// y0: f32, -// x1: f32, -// y1: f32, -// ) -> f32 { -// let dx = x1 - x0; -// let dy = y1 - y0; -// let length_sq = dx * dx + dy * dy; - -// if length_sq < 0.001 { -// // Line segment is actually a point -// let dpx = px - x0; -// let dpy = py - y0; -// return (dpx * dpx + dpy * dpy).sqrt(); -// } - -// // Calculate parameter t for the closest point on the line segment -// let t = ((px - x0) * dx + (py - y0) * dy) / length_sq; -// let t = t.max(0.0).min(1.0); // Clamp to [0, 1] to stay on segment - -// // Find the closest point on the line segment -// let closest_x = x0 + t * dx; -// let closest_y = y0 + t * dy; - -// // Return distance to closest point -// let dpx = px - closest_x; -// let dpy = py - closest_y; -// (dpx * dpx + dpy * dpy).sqrt() -// } - -// /// Calculates alpha value based on distance from line edge -// fn calculate_alpha(&self, distance: f32, half_thickness: f32) -> f32 { -// if distance <= half_thickness - 0.5 { -// // Inside the line core - full opacity -// 1.0 -// } else if distance <= half_thickness + 0.5 { -// // In the antialiasing zone - linear falloff -// half_thickness + 0.5 - distance -// } else { -// // Outside the line - transparent -// 0.0 -// } -// } - -// // // Draw a thick line by creating a capsule shape -// // fn draw_line(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, width: usize, color: u8) { -// // let half_width = width as f32 / 2.0; - -// // // Calculate line vector and length -// // let dx = (x2 - x1) as f32; -// // let dy = (y2 - y1) as f32; -// // let length = (dx * dx + dy * dy).sqrt(); - -// // // if length < 0.001 { -// // // // Degenerate case: just draw a circle -// // // self.draw_circle(x1, y1, half_width as i32, color); -// // // return; -// // // } - -// // // Normalize the line direction -// // let nx = dx / length; -// // let ny = dy / length; - -// // // Calculate perpendicular vector for line thickness -// // let px = -ny * half_width; -// // let py = nx * half_width; - -// // // Get the four corners of the rectangle -// // let corner1_x = (x1 as f32 + px) as usize; -// // let corner1_y = (y1 as f32 + py) as usize; -// // let corner2_x = (x1 as f32 - px) as usize; -// // let corner2_y = (y1 as f32 - py) as usize; -// // let corner3_x = (x2 as f32 - px) as usize; -// // let corner3_y = (y2 as f32 - py) as usize; -// // let corner4_x = (x2 as f32 + px) as usize; -// // let corner4_y = (y2 as f32 + py) as usize; - -// // // Draw the main rectangle body -// // self.fill_quadrilateral( -// // corner1_x, corner1_y, corner2_x, corner2_y, corner3_x, corner3_y, corner4_x, corner4_y, -// // color, -// // ); - -// // // // Draw rounded ends -// // // let radius = (half_width) as i32; -// // // self.draw_circle(x1, y1, radius, color); -// // // self.draw_circle(x2, y2, radius, color); -// // } - -// // fn fill_quadrilateral( -// // &mut self, -// // x1: usize, -// // y1: usize, -// // x2: usize, -// // y2: usize, -// // x3: usize, -// // y3: usize, -// // x4: usize, -// // y4: usize, -// // color: u8, -// // ) { -// // // Find bounding box -// // let binding_x = [x1, x2, x3, x4]; -// // let binding_y = [y1, y2, y3, y4]; -// // let min_x = binding_x.iter().min().unwrap(); -// // let max_x = binding_x.iter().max().unwrap(); -// // let min_y = binding_y.iter().min().unwrap(); -// // let max_y = binding_y.iter().max().unwrap(); - -// // // For each point in bounding box, test if it's inside the quadrilateral -// // for y in *min_y..=*max_y { -// // for x in *min_x..=*max_x { -// // if self.point_in_quad(x, y, x1, y1, x2, y2, x3, y3, x4, y4) { -// // self.set_pixel(x, y, color); -// // } -// // } -// // } -// // } - -// // // Test if a point is inside a quadrilateral using cross products -// // fn point_in_quad( -// // &self, -// // px: usize, -// // py: usize, -// // x1: usize, -// // y1: usize, -// // x2: usize, -// // y2: usize, -// // x3: usize, -// // y3: usize, -// // x4: usize, -// // y4: usize, -// // ) -> bool { -// // // Test against each edge of the quadrilateral -// // let sign1 = self.cross_product(px - x1, py - y1, x2 - x1, y2 - y1); -// // let sign2 = self.cross_product(px - x2, py - y2, x3 - x2, y3 - y2); -// // let sign3 = self.cross_product(px - x3, py - y3, x4 - x3, y4 - y3); -// // let sign4 = self.cross_product(px - x4, py - y4, x1 - x4, y1 - y4); - -// // // Point is inside if all cross products have the same sign -// // (sign1 >= 0 && sign2 >= 0 && sign3 >= 0 && sign4 >= 0) -// // || (sign1 <= 0 && sign2 <= 0 && sign3 <= 0 && sign4 <= 0) -// // } - -// // // Calculate 2D cross product -// // fn cross_product(&self, ax: usize, ay: usize, bx: usize, by: usize) -> usize { -// // ax * by - ay * bx -// // } - -// // fn set_pixel(&mut self, x: usize, y: usize, color: u8) { -// // self.data[y*self.width + x] = color; -// // } -// } - pub struct Bitmap { pub data: Vec, pub width: usize, diff --git a/src/views/color_rect_view.rs b/src/views/color_rect_view.rs index 0f798b4..b3de4ec 100644 --- a/src/views/color_rect_view.rs +++ b/src/views/color_rect_view.rs @@ -25,29 +25,10 @@ impl ColorRectView { constraints: (None, None, None, None), } } -} - -impl View for ColorRectView { - fn draw(&mut self, renderer: &mut Renderer, x: f32, y: f32, w: f32, h: f32) { - renderer.rect_xywh(x as i32, y as i32, w as i32, h as i32, self.color); - // log!("Draw"); - } -} - -impl LayoutView for ColorRectView { - fn set_bounds(&mut self, width: Option, height: Option) { + pub fn set_bounds(&mut self, width: Option, height: Option) { self.bounds = (width, height); } - fn bounds(&self, _ph: f32, _pw: f32) -> (Bounds, Bounds) { - ( - *self.bounds.0.as_ref().unwrap_or(&Bounds::Pixels(100.)), - self.bounds.1.unwrap_or(Bounds::Pixels(100.)), - ) - } -} - -impl ConstraintView for ColorRectView { - fn set_constraints( + pub fn set_constraints( &mut self, top: Option, left: Option, @@ -56,7 +37,27 @@ impl ConstraintView for ColorRectView { ) { self.constraints = (top, left, right, bottom) } +} +impl View for ColorRectView { + fn draw(&mut self, renderer: &mut Renderer, x: f32, y: f32, w: f32, h: f32) { + renderer.rect_xywh(x as i32, y as i32, w as i32, h as i32, self.color); + // log!("Draw"); + } + + fn resize(&mut self, x: f32, y: f32, w: f32, h: f32) {} +} + +impl LayoutView for ColorRectView { + fn bounds(&self, _ph: f32, _pw: f32) -> (Bounds, Bounds) { + ( + *self.bounds.0.as_ref().unwrap_or(&Bounds::Pixels(100.)), + *self.bounds.1.as_ref().unwrap_or(&Bounds::Pixels(100.)), + ) + } +} + +impl ConstraintView for ColorRectView { fn get_constraints( &self, ) -> ( diff --git a/src/views/constraint_layout.rs b/src/views/constraint_layout.rs index 3ba7f69..44d8213 100644 --- a/src/views/constraint_layout.rs +++ b/src/views/constraint_layout.rs @@ -1,7 +1,6 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use crate::{ - log, render::Renderer, views::{LayoutView, View}, }; @@ -19,13 +18,6 @@ pub enum Constraint { } pub trait ConstraintView: LayoutView { - fn set_constraints( - &mut self, - top: Option, - left: Option, - right: Option, - bottom: Option, - ); fn get_constraints( &self, ) -> ( @@ -38,7 +30,7 @@ pub trait ConstraintView: LayoutView { pub struct ConstraintLayout { pub children: Vec>, - child_positions: Option>, + child_positions: Option>, } struct Rect { @@ -63,35 +55,13 @@ impl ConstraintLayout { ); } - let this = ConstraintLayout { + ConstraintLayout { children, child_positions: None, - }; - - this.test(); - - this - } - pub fn test(&self) { - let dependencies = self - .children - .iter() - .map(|c| { - let constraints = c.get_constraints(); - [constraints.0, constraints.1, constraints.2, constraints.3] - }) - .collect::>(); - - let dac = topological_sort(&dependencies); - - for i in 0..dac.len() { - log!("{:?}", dac[i]) } } -} -impl View for ConstraintLayout { - fn draw(&mut self, renderer: &mut Renderer, x: f32, y: f32, self_w: f32, self_h: f32) { + pub fn recalculate_positions(&mut self, x: f32, y: f32, self_w: f32, self_h: f32) { let self_top = y; let self_left = x; let self_right = x + self_w; @@ -126,46 +96,40 @@ impl View for ConstraintLayout { crate::views::Bounds::Pixels(x) => x, }; - let (y, height) = match (c_top, c_bottom) { - (None, None) => unreachable!("Vertically unconstrained"), - (Some(Constraint::TopParent(top_margin)), None) => { - (self_top + top_margin, c_height) + let y_align = |constraint: &Option| match constraint { + Some(Constraint::TopParent(margin)) => Some(self_top + margin), + Some(Constraint::BottomParent(margin)) => Some(self_bottom - margin), + Some(Constraint::Top(margin, id)) => { + let other = calculated_positions.get(&id).unwrap(); + Some(other.y - margin) } - (Some(Constraint::BottomParent(top_margin)), None) => { - (self_top + top_margin + c_height, c_height) + + Some(Constraint::Bottom(margin, id)) => { + let other = calculated_positions.get(&id).unwrap(); + Some(other.y + other.height + margin) } - (None, Some(Constraint::TopParent(top_margin))) => { - (self_top - top_margin, c_height) - } - (None, Some(Constraint::BottomParent(bottom_margin))) => { - (self_h - (bottom_margin + c_height), c_height) - } - (Some(Constraint::TopParent(_)), Some(Constraint::TopParent(_))) => unreachable!(), - (Some(Constraint::BottomParent(_)), Some(Constraint::BottomParent(_))) => { - unreachable!() - } - (Some(Constraint::BottomParent(_)), Some(Constraint::TopParent(_))) => { - unreachable!() - } - (Some(Constraint::TopParent(_)), Some(Constraint::BottomParent(top_margin))) => { - (self_top + top_margin + c_height, c_height) - } - _ => todo!(), + None => None, + _ => unreachable!(), }; - assert!(height >= 0.); + let y = match (y_align(c_top), y_align(c_bottom)) { + (Some(top), Some(bottom)) => (bottom + top - c_height) / 2., + (Some(top), None) => top, + (None, Some(bottom)) => bottom - c_height, + (None, None) => unreachable!("Vertically unconstrained"), + }; let x_align = |constraint: &Option| match constraint { Some(Constraint::LeftParent(margin)) => Some(self_left + margin), Some(Constraint::RightParent(margin)) => Some(self_right - margin), Some(Constraint::Left(margin, id)) => { let other = calculated_positions.get(&id).unwrap(); - Some(other.x - margin - c_width) + Some(other.x - margin) } Some(Constraint::Right(margin, id)) => { let other = calculated_positions.get(&id).unwrap(); - Some(other.x + other.width + margin) + Some(other.x + other.width - margin) } None => None, _ => unreachable!(), @@ -178,82 +142,33 @@ impl View for ConstraintLayout { (None, None) => unreachable!("Horizontally unconstrained"), }; - // let (x, width) = match (c_left, c_right) { - // (None, None) => unreachable!("Vertically unconstrained"), - // (Some(Constraint::LeftParent(left_margin)), None) => { - // (self_top + left_margin, width) - // } - // (Some(Constraint::RightParent(right_margin)), None) => { - // (self_top - right_margin + width, width) - // } - // (None, Some(Constraint::LeftParent(left_margin))) => { - // (self_top - left_margin, width) - // } - // (None, Some(Constraint::RightParent(right_margin))) => { - // (self_w - (right_margin + width), width) - // // (self_top + top_margin + height, height) - // } - // (Some(Constraint::Left(left_margin, n)), None) => { - // let other = calculated_positions.get(n).unwrap(); - // (other.x - (width + left_margin), width) - // } - // (Some(Constraint::Right(right_margin, idx)), None) => { - // (self_top - right_margin + width, width) - // } - // (None, Some(Constraint::Left(left_margin, idx))) => (self_top - left_margin, width), - // (None, Some(Constraint::Right(right_margin, idx))) => { - // (self_w - (right_margin + width), width) - // // (self_top + top_margin + height, height) - // } - // (Some(Constraint::LeftParent(_)), Some(Constraint::LeftParent(_))) => { - // unreachable!() - // } - // (Some(Constraint::RightParent(_)), Some(Constraint::RightParent(_))) => { - // unreachable!() - // } - // (Some(Constraint::RightParent(_)), Some(Constraint::LeftParent(_))) => { - // unreachable!() - // } - // (Some(Constraint::TopParent(_)), Some(Constraint::BottomParent(top_margin))) => { - // (self_top + top_margin + width, width) - // } - // _ => todo!(), - // }; - - assert!(c_width >= 0.); - calculated_positions.insert( idx, Rect { x: x, y: y, width: c_width, - height: height, + height: c_height, }, ); - child.draw(renderer, x, y, c_width, height); - - // match c_top { - // None => {} - // Some(Constraint::TopParent(top_margin)) => { - - // // let child_top = self_top + top_margin; - // // let child_left = self_left; - // // let child_right = self_right; - // // let child_bottom = child_top + child.get_height(); - - // // child.draw(renderer, child_left, child_top, child_right - child_left, child_bottom - child_top); - // } - // _ => unreachable!(), - // } - - // match - - // let child_top = child_top.unwrap_or(self_top); - // let child_left = child_left.unwrap_or(self_left); - // let child_right = child_right.unwrap_or(self_right); - // let child_bottom = child_bottom.unwrap_or(self_bottom); } + + self.child_positions = Some(calculated_positions); + } +} + +impl View for ConstraintLayout { + fn draw(&mut self, renderer: &mut Renderer, _x: f32, _y: f32, _self_w: f32, _self_h: f32) { + if let Some(child_positions) = &mut self.child_positions { + for i in 0..self.children.len() { + let rect = child_positions.get(&i).unwrap(); + self.children[i].draw(renderer, rect.x, rect.y, rect.width, rect.height); + } + } + } + + fn resize(&mut self, x: f32, y: f32, w: f32, h: f32) { + self.recalculate_positions(x, y, w, h); } } @@ -323,9 +238,3 @@ fn get_dependency(constraint: &Constraint) -> Option { _ => None, // Parent constraints have no dependencies } } - -// impl LayoutView for ConstraintLayout { -// fn set_bounds(&mut self, width: Option, height: Option) { -// // Implement bounds setting logic here -// } -// } diff --git a/src/views/mod.rs b/src/views/mod.rs index 811a76a..d1c2ab4 100644 --- a/src/views/mod.rs +++ b/src/views/mod.rs @@ -14,6 +14,7 @@ use vertical_layout::VerticalLayout; pub trait View { fn draw(&mut self, renderer: &mut Renderer, x: f32, y: f32, w: f32, h: f32); + fn resize(&mut self, x: f32, y: f32, w: f32, h: f32); } #[derive(Debug, Clone, Copy, PartialEq)] @@ -23,7 +24,7 @@ pub enum Bounds { } pub trait LayoutView: View { - fn set_bounds(&mut self, width: Option, height: Option); + // fn set_bounds(&mut self, width: Option, height: Option); fn bounds(&self, pw: f32, ph: f32) -> (Bounds, Bounds); } @@ -39,9 +40,11 @@ pub fn default_view() -> Box { a.set_constraints( Some(Constraint::TopParent(temp_margin)), None, - Some(Constraint::Left(temp_margin, 2)), - Some(Constraint::BottomParent(temp_margin)), + Some(Constraint::Left(temp_margin, 1)), + None, + // Some(Constraint::BottomParent(temp_margin)), ); + a.set_bounds(Some(Bounds::Pixels(200.)), Some(Bounds::Pixels(100.))); let mut b = ColorRectView::new(0, 127, 0); @@ -70,11 +73,34 @@ pub fn default_view() -> Box { Some(Constraint::BottomParent(temp_margin)), ); + let mut center = ColorRectView::new(127, 127, 0); + + center.set_constraints( + Some(Constraint::TopParent(temp_margin)), + Some(Constraint::LeftParent(temp_margin)), + Some(Constraint::RightParent(temp_margin)), + Some(Constraint::BottomParent(temp_margin)), + ); + + center.set_bounds(Some(Bounds::Pixels(350.)), Some(Bounds::Pixels(100.))); + + let mut center_top = ColorRectView::new(127, 0, 127); + + center_top.set_constraints( + None, + // Some(Constraint::Left(0., 4)), + None, + Some(Constraint::Right(0., 4)), + Some(Constraint::Top(20., 4)), + ); + Box::new(ConstraintLayout::new(vec![ Box::new(a), Box::new(b), Box::new(c), Box::new(d), + Box::new(center), + Box::new(center_top), ])) // Box::new(VerticalLayout::new(vec![ diff --git a/src/views/text_view.rs b/src/views/text_view.rs index 15eb1f1..de439fe 100644 --- a/src/views/text_view.rs +++ b/src/views/text_view.rs @@ -39,21 +39,13 @@ impl TextView { s } + pub fn set_bounds(&mut self, width: Option, height: Option) { + self.bounds = (width, height); + } } impl View for TextView { fn draw(&mut self, renderer: &mut Renderer, x: f32, y: f32, w: f32, h: f32) { - // renderer.rasterize_font( - // x as i32, - // y as i32, - // &self.text, - // 20., - // FontHandle::AtiksonHyperlegibleRegular, - // ); - // renderer. - - // renderer.rect_xywh(x as i32, y as i32, w as i32, h as i32, self.color); - let (x, y) = renderer.undistort(x as f32, y as f32); let (mut width, mut height): (usize, usize) = (0, 0); @@ -82,12 +74,13 @@ impl View for TextView { // new_bitmap } + + fn resize(&mut self, x: f32, y: f32, w: f32, h: f32) { + // todo!() + } } impl LayoutView for TextView { - fn set_bounds(&mut self, width: Option, height: Option) { - self.bounds = (width, height); - } fn bounds(&self, _ph: f32, _pw: f32) -> (Bounds, Bounds) { // let (x, y) = renderer.undistort(x as f32, y as f32); diff --git a/src/views/vertical_layout.rs b/src/views/vertical_layout.rs index 21bdd00..5cb1bd4 100644 --- a/src/views/vertical_layout.rs +++ b/src/views/vertical_layout.rs @@ -12,6 +12,9 @@ impl VerticalLayout { bounds: (None, None), } } + pub fn set_bounds(&mut self, width: Option, height: Option) { + self.bounds = (width, height); + } } impl View for VerticalLayout { @@ -38,13 +41,10 @@ impl View for VerticalLayout { } } } + fn resize(&mut self, x: f32, y: f32, w: f32, h: f32) {} } impl LayoutView for VerticalLayout { - fn set_bounds(&mut self, width: Option, height: Option) { - self.bounds = (width, height); - } - fn bounds(&self, pw: f32, ph: f32) -> (Bounds, Bounds) { let (mut maxx, mut totaly): (f32, f32) = (0., 0.); for view in &self.views {