#![allow(clippy::new_without_default)] use crate::{layout::Direction, GuiResponse, *}; mod slider; mod text_edit; pub use {slider::*, text_edit::*}; // ---------------------------------------------------------------------------- /// Anything implementing Widget can be added to a Ui with `Ui::add` pub trait Widget { fn ui(self, ui: &mut Ui) -> GuiResponse; } // ---------------------------------------------------------------------------- pub struct Label { // TODO: not pub pub(crate) text: String, pub(crate) multiline: bool, auto_shrink: bool, pub(crate) text_style: TextStyle, // TODO: Option, where None means "use the default for the ui" pub(crate) text_color: Option, } impl Label { pub fn new(text: impl Into) -> Self { Self { text: text.into(), multiline: true, auto_shrink: false, text_style: TextStyle::Body, text_color: None, } } pub fn text(&self) -> &str { &self.text } pub fn multiline(mut self, multiline: bool) -> Self { self.multiline = multiline; self } /// If true, will word wrap to `ui.available_finite().width()`. /// If false (default), will word wrap to `ui.available().width()`. /// This only makes a difference for auto-sized parents. pub fn auto_shrink(mut self) -> Self { self.auto_shrink = true; self } pub fn text_style(mut self, text_style: TextStyle) -> Self { self.text_style = text_style; self } pub fn text_color(mut self, text_color: Color) -> Self { self.text_color = Some(text_color); self } pub fn layout(&self, max_width: f32, ui: &Ui) -> (Vec, Vec2) { let font = &ui.fonts()[self.text_style]; if self.multiline { font.layout_multiline(&self.text, max_width) } else { font.layout_single_line(&self.text) } } // TODO: this should return a LabelLayout which has a paint method. // We can then split Widget::Ui in two: layout + allocating space, and painting. // this allows us to assemble lables, THEN detect interaction, THEN chose color style based on that. // pub fn layout(self, ui: &mut ui) -> LabelLayout { } // TODO: a paint method for painting anywhere in a ui. // This should be the easiest method of putting text anywhere. } /// Usage: label!("Foo: {}", bar) #[macro_export] macro_rules! label { ($fmt:expr) => ($crate::widgets::Label::new($fmt)); ($fmt:expr, $($arg:tt)*) => ($crate::widgets::Label::new(format!($fmt, $($arg)*))); } impl Widget for Label { fn ui(self, ui: &mut Ui) -> GuiResponse { let max_width = if self.auto_shrink { ui.available_finite().width() } else { ui.available().width() }; let (text, text_size) = self.layout(max_width, ui); let interact = ui.reserve_space(text_size, None); ui.add_text(interact.rect.min, self.text_style, text, self.text_color); ui.response(interact) } } impl Into