sized widgets!
This commit is contained in:
@@ -6,7 +6,7 @@ pub struct Regioned {
|
||||
}
|
||||
|
||||
impl Widget for Regioned {
|
||||
fn draw(&self, painter: &mut Painter) {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
painter.draw_within(&self.inner, self.region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,34 +2,23 @@ use crate::prelude::*;
|
||||
use image::DynamicImage;
|
||||
|
||||
pub struct Image {
|
||||
handle: Option<TextureHandle>,
|
||||
handle: TextureHandle,
|
||||
}
|
||||
|
||||
impl Widget for Image {
|
||||
fn draw(&self, painter: &mut Painter) {
|
||||
if let Some(handle) = &self.handle {
|
||||
painter.draw_texture(handle);
|
||||
} else {
|
||||
painter.write(RectPrimitive {
|
||||
color: Color::MAGENTA,
|
||||
inner_radius: 0.0,
|
||||
radius: 0.0,
|
||||
thickness: 0.0,
|
||||
});
|
||||
}
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
painter.draw_texture(&self.handle);
|
||||
}
|
||||
|
||||
fn size(&mut self, _: SizeCtx) -> Vec2 {
|
||||
self.handle.size()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image(image: impl LoadableImage) -> WidgetFnRet!(Image) {
|
||||
let image = match image.get_image() {
|
||||
Ok(image) => Some(image),
|
||||
Err(e) => {
|
||||
println!("Failed to load image: {e}");
|
||||
None
|
||||
}
|
||||
};
|
||||
let image = image.get_image().expect("Failed to load image");
|
||||
move |ui| Image {
|
||||
handle: image.map(|image| ui.add_texture(image)),
|
||||
handle: ui.add_texture(image),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ impl Rect {
|
||||
}
|
||||
|
||||
impl Widget for Rect {
|
||||
fn draw(&self, painter: &mut Painter) {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
painter.write(RectPrimitive {
|
||||
color: self.color,
|
||||
radius: self.radius,
|
||||
|
||||
@@ -6,8 +6,8 @@ pub struct Span {
|
||||
}
|
||||
|
||||
impl Widget for Span {
|
||||
fn draw(&self, painter: &mut Painter) {
|
||||
let total = self.sums();
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
let total = self.setup(painter);
|
||||
let mut start = UIScalar::min();
|
||||
for (child, length) in &self.children {
|
||||
let mut child_region = UiRegion::full();
|
||||
@@ -29,6 +29,14 @@ impl Widget for Span {
|
||||
start.anchor += rel;
|
||||
axis.bot_right.set(start);
|
||||
}
|
||||
SpanLen::Sized(size) => {
|
||||
let offset = size.axis(self.dir.axis);
|
||||
start.offset += offset;
|
||||
*axis.bot_right.offset = start.offset;
|
||||
child_region.bot_right.anchor = child_region.top_left.anchor;
|
||||
let opposite = !self.dir.axis;
|
||||
*child_region.bot_right.offset.axis_mut(opposite) += size.axis(opposite);
|
||||
}
|
||||
}
|
||||
if self.dir.sign == Sign::Neg {
|
||||
child_region.flip();
|
||||
@@ -53,18 +61,23 @@ impl Span {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sums(&self) -> SpanLenSums {
|
||||
self.lengths().fold(SpanLenSums::default(), |mut s, l| {
|
||||
match l {
|
||||
SpanLen::Fixed(v) => s.fixed += v,
|
||||
SpanLen::Ratio(v) => s.ratio += v,
|
||||
SpanLen::Relative(v) => s.relative += v,
|
||||
}
|
||||
s
|
||||
})
|
||||
}
|
||||
pub fn lengths(&self) -> impl ExactSizeIterator<Item = &SpanLen> {
|
||||
self.children.iter().map(|(_, s)| s)
|
||||
fn setup(&mut self, painter: &mut Painter) -> SpanLenSums {
|
||||
self.children
|
||||
.iter_mut()
|
||||
.fold(SpanLenSums::default(), |mut s, (id, l)| {
|
||||
match l {
|
||||
SpanLen::Fixed(v) => s.fixed += *v,
|
||||
SpanLen::Ratio(v) => s.ratio += *v,
|
||||
SpanLen::Relative(v) => s.relative += *v,
|
||||
SpanLen::Sized(v) => {
|
||||
let size = painter.size(id);
|
||||
let len = size.axis(self.dir.axis);
|
||||
*v = size;
|
||||
s.fixed += len;
|
||||
}
|
||||
}
|
||||
s
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +91,10 @@ pub enum SpanLen {
|
||||
/// relative to the total space (of the entire span)
|
||||
/// eg. 0.5 means 1/2 of the total space
|
||||
Relative(f32),
|
||||
/// size determined by the child widget itself
|
||||
/// the value is not used externally, I just don't wanna make a duplicate enum
|
||||
/// there are util functions instead so
|
||||
Sized(Vec2),
|
||||
}
|
||||
|
||||
pub fn fixed<N: UiNum>(x: N) -> SpanLen {
|
||||
@@ -92,6 +109,10 @@ pub fn relative<N: UiNum>(x: N) -> SpanLen {
|
||||
SpanLen::Relative(x.to_f32())
|
||||
}
|
||||
|
||||
pub fn sized() -> SpanLen {
|
||||
SpanLen::Sized(Vec2::ZERO)
|
||||
}
|
||||
|
||||
impl<N: UiNum> From<N> for SpanLen {
|
||||
fn from(value: N) -> Self {
|
||||
Self::Ratio(value.to_f32())
|
||||
|
||||
@@ -5,7 +5,7 @@ pub struct Stack {
|
||||
}
|
||||
|
||||
impl Widget for Stack {
|
||||
fn draw(&self, painter: &mut Painter) {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
for child in &self.children {
|
||||
painter.draw(child);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
use cosmic_text::Metrics;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct Text {
|
||||
pub content: String,
|
||||
pub attrs: TextAttrs,
|
||||
buf: TextBuffer,
|
||||
}
|
||||
|
||||
impl Text {
|
||||
pub fn size(mut self, size: impl UiNum) -> Self {
|
||||
self.attrs.size = size.to_f32();
|
||||
self.attrs.line_height = self.attrs.size * 1.1;
|
||||
self
|
||||
}
|
||||
pub fn color(mut self, color: UiColor) -> Self {
|
||||
@@ -21,16 +25,31 @@ impl Text {
|
||||
}
|
||||
|
||||
impl Widget for Text {
|
||||
fn draw(&self, painter: &mut Painter) {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
let (handle, offset) = painter.render_text(&mut self.buf, &self.content, &self.attrs);
|
||||
let dims = handle.size();
|
||||
let size = offset.size(&handle);
|
||||
let mut region = painter.region().center().expand(size);
|
||||
region.top_left.offset += offset.top_left;
|
||||
region.bot_right.offset = region.top_left.offset + dims;
|
||||
painter.draw_texture_at(&handle, region);
|
||||
// TODO: when on_update is added to painter,
|
||||
// return & store TextureHandle to reuse
|
||||
painter.draw_text(&self.content, &self.attrs);
|
||||
// reuse TextureHandle
|
||||
}
|
||||
|
||||
fn size(&mut self, ctx: SizeCtx) -> Vec2 {
|
||||
let (handle, offset) =
|
||||
ctx.text
|
||||
.draw(&mut self.buf, &self.content, &self.attrs, ctx.textures);
|
||||
offset.size(&handle)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text(text: impl Into<String>) -> Text {
|
||||
let attrs = TextAttrs::default();
|
||||
Text {
|
||||
content: text.into(),
|
||||
attrs: TextAttrs::default(),
|
||||
buf: TextBuffer::new_empty(Metrics::new(attrs.size, attrs.line_height)),
|
||||
attrs,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user