diff --git a/emigui/src/containers/area.rs b/emigui/src/containers/area.rs index 17e45d29..5470a937 100644 --- a/emigui/src/containers/area.rs +++ b/emigui/src/containers/area.rs @@ -115,7 +115,7 @@ impl Area { Rect::from_min_size(state.pos, Vec2::infinity()), ); add_contents(&mut ui); - state.size = ui.bounding_size().ceil(); + state.size = (ui.child_bounds().max - state.pos).ceil(); let rect = Rect::from_min_size(state.pos, state.size); let clip_rect = Rect::everything(); // TODO: get from context diff --git a/emigui/src/containers/collapsing_header.rs b/emigui/src/containers/collapsing_header.rs index 72216f90..7b2e40d3 100644 --- a/emigui/src/containers/collapsing_header.rs +++ b/emigui/src/containers/collapsing_header.rs @@ -56,16 +56,14 @@ impl CollapsingHeader { // TODO: horizontal layout, with icon and text as labels. Insert background behind using Frame. - let title = &label.text; // TODO: not this + let title = label.text(); let id = ui.make_unique_id(title); - let text_pos = ui.cursor() + vec2(ui.style().indent, 0.0); - let (title, text_size) = label.layout(text_pos, ui); + + let available = ui.available_finite(); + let text_pos = available.min + vec2(ui.style().indent, 0.0); + let (text, text_size) = label.layout(available.width() - ui.style().indent, ui); let text_max_x = text_pos.x + text_size.x; - let desired_width = ui - .available_finite() - .size() - .x - .max(text_max_x - ui.cursor().x); + let desired_width = available.width().max(text_max_x - available.left()); let interact = ui.reserve_space( vec2( @@ -96,7 +94,7 @@ impl CollapsingHeader { ui.add_text( text_pos, label.text_style, - title, + text, Some(ui.style().interact(&interact).stroke_color), ); diff --git a/emigui/src/containers/menu.rs b/emigui/src/containers/menu.rs index 0709dddf..e6a69147 100644 --- a/emigui/src/containers/menu.rs +++ b/emigui/src/containers/menu.rs @@ -20,7 +20,7 @@ impl Default for BarState { } } -pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) { +pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { ui.horizontal(|ui| { Frame::default().show(ui, |ui| { let mut style = ui.style().clone(); diff --git a/emigui/src/containers/resize.rs b/emigui/src/containers/resize.rs index c6003fc4..76f597c1 100644 --- a/emigui/src/containers/resize.rs +++ b/emigui/src/containers/resize.rs @@ -159,7 +159,7 @@ impl Resize { state.size = state.size.clamp(self.min_size..=self.max_size); let last_frame_size = state.size; - let position = ui.cursor(); + let position = ui.available().min; let corner_interact = if self.resizable { // Resize-corner: @@ -189,7 +189,7 @@ impl Resize { // ------------------------------ - let inner_rect = Rect::from_min_size(ui.cursor(), state.size); + let inner_rect = Rect::from_min_size(position, state.size); let desired_size = { let mut content_clip_rect = ui .clip_rect() diff --git a/emigui/src/containers/scroll_area.rs b/emigui/src/containers/scroll_area.rs index e66cf25a..65e7f734 100644 --- a/emigui/src/containers/scroll_area.rs +++ b/emigui/src/containers/scroll_area.rs @@ -74,10 +74,10 @@ impl ScrollArea { ); let inner_size = outer_size - vec2(current_scroll_bar_width, 0.0); - let inner_rect = Rect::from_min_size(outer_ui.cursor(), inner_size); + let inner_rect = Rect::from_min_size(outer_ui.available().min, inner_size); let mut content_ui = outer_ui.child_ui(Rect::from_min_size( - outer_ui.cursor() - state.offset, + inner_rect.min - state.offset, vec2(inner_size.x, f32::INFINITY), )); let mut content_clip_rect = outer_ui.clip_rect().intersect(inner_rect); diff --git a/emigui/src/examples/app.rs b/emigui/src/examples/app.rs index 1983ea8d..4a4b37af 100644 --- a/emigui/src/examples/app.rs +++ b/emigui/src/examples/app.rs @@ -353,9 +353,9 @@ impl Painting { } ui.add_custom_contents(vec2(f32::INFINITY, 200.0), |ui| { - let canvas_corner = ui.cursor(); - let interact = ui.reserve_space(ui.available().size(), Some(ui.id())); - ui.set_clip_rect(ui.clip_rect().intersect(interact.rect)); // Make sure we don't paint out of bounds + let interact = ui.reserve_space(ui.available_finite().size(), Some(ui.id())); + let rect = interact.rect; + ui.set_clip_rect(ui.clip_rect().intersect(rect)); // Make sure we don't paint out of bounds if self.lines.is_empty() { self.lines.push(vec![]); @@ -365,7 +365,7 @@ impl Painting { if interact.active { if let Some(mouse_pos) = ui.input().mouse_pos { - let canvas_pos = mouse_pos - canvas_corner; + let canvas_pos = mouse_pos - rect.min; if current_line.last() != Some(&canvas_pos) { current_line.push(canvas_pos); } @@ -377,7 +377,7 @@ impl Painting { for line in &self.lines { if line.len() >= 2 { ui.add_paint_cmd(PaintCmd::LinePath { - points: line.iter().map(|p| canvas_corner + *p).collect(), + points: line.iter().map(|p| rect.min + *p).collect(), color: LIGHT_GRAY, width: 2.0, }); diff --git a/emigui/src/ui.rs b/emigui/src/ui.rs index 196cdfbf..3ae3a3d9 100644 --- a/emigui/src/ui.rs +++ b/emigui/src/ui.rs @@ -235,25 +235,25 @@ impl Ui { /// This how much more space we can take up without overflowing our parent. /// Shrinks as widgets allocate space and the cursor moves. /// A small rectangle should be intepreted as "as little as possible". - /// An infinite rectangle should be interpred as "as much as you want" + /// An infinite rectangle should be interpred as "as much as you want". + /// In most layouts the next widget will be put in the top left corner of this `Rect`. pub fn available(&self) -> Rect { Rect::from_min_max(self.cursor, self.bottom_right()) } /// This is like `available()`, but will never be infinite. /// Use this for components that want to grow without bounds (but shouldn't). + /// In most layouts the next widget will be put in the top left corner of this `Rect`. pub fn available_finite(&self) -> Rect { Rect::from_min_max(self.cursor, self.finite_bottom_right()) } + // TODO: remove pub fn direction(&self) -> Direction { self.dir } - pub fn cursor(&self) -> Pos2 { - self.cursor - } - + // TODO: remove pub fn set_align(&mut self, align: Align) { self.align = align; } @@ -278,11 +278,11 @@ impl Ui { /// Use this to generate widget ids for widgets that have persistent state in Memory. /// If the `id_source` is not unique within this ui /// then an error will be printed at the current cursor position. - pub fn make_unique_id(&self, id_source: &IdSource) -> Id + pub fn make_unique_id(&self, id_source: IdSource) -> Id where IdSource: Hash + std::fmt::Debug, { - let id = self.id.with(id_source); + let id = self.id.with(&id_source); // TODO: clip name clash error messages to clip rect self.ctx.register_unique_id(id, id_source, self.cursor) } @@ -544,9 +544,7 @@ impl Ui { pub fn add_custom_contents(&mut self, size: Vec2, add_contents: impl FnOnce(&mut Ui)) { let size = size.min(self.available().size()); let child_rect = Rect::from_min_size(self.cursor, size); - let mut child_ui = Ui { - ..self.child_ui(child_rect) - }; + let mut child_ui = self.child_ui(child_rect); add_contents(&mut child_ui); self.reserve_space(child_ui.bounding_size(), None); } @@ -614,12 +612,12 @@ impl Ui { } /// Start a ui with horizontal layout - pub fn horizontal(&mut self, add_contents: impl FnOnce(&mut Ui)) { + pub fn horizontal(&mut self, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { self.inner_layout(Direction::Horizontal, Align::Min, add_contents) } /// Start a ui with vertical layout - pub fn vertical(&mut self, add_contents: impl FnOnce(&mut Ui)) { + pub fn vertical(&mut self, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { self.inner_layout(Direction::Vertical, Align::Min, add_contents) } @@ -628,7 +626,7 @@ impl Ui { dir: Direction, align: Align, add_contents: impl FnOnce(&mut Self), - ) { + ) -> InteractInfo { let child_rect = Rect::from_min_max(self.cursor, self.bottom_right()); let mut child_ui = Self { dir, @@ -637,7 +635,7 @@ impl Ui { }; add_contents(&mut child_ui); let size = child_ui.bounding_size(); - self.reserve_space(size, None); + self.reserve_space(size, None) } /// Temporarily split split a vertical layout into several columns. diff --git a/emigui/src/widgets.rs b/emigui/src/widgets.rs index d6fd0240..1590e6b7 100644 --- a/emigui/src/widgets.rs +++ b/emigui/src/widgets.rs @@ -48,8 +48,8 @@ impl Label { self } - /// If true, will word wrap to the width of the current child_bounds. - /// If false (defailt), will word wrap to the available width + /// If true, will word wrap to `ui.available_finite().width()`. + /// If false (default), will word wrap to `ui.available().width()`. pub fn auto_shrink(mut self) -> Self { self.auto_shrink = true; self @@ -65,15 +65,8 @@ impl Label { self } - pub fn layout(&self, pos: Pos2, ui: &Ui) -> (Vec, Vec2) { + pub fn layout(&self, max_width: f32, ui: &Ui) -> (Vec, Vec2) { let font = &ui.fonts()[self.text_style]; - - let max_width = if self.auto_shrink { - ui.child_bounds().right() - pos.x - } else { - ui.rect().right() - pos.x - }; - if self.multiline { font.layout_multiline(&self.text, max_width) } else { @@ -99,7 +92,12 @@ macro_rules! label { impl Widget for Label { fn ui(self, ui: &mut Ui) -> GuiResponse { - let (text, text_size) = self.layout(ui.cursor(), ui); + 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)