From 5ea94dd0d74551c7a2517d11ae360243c81e3097 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 14 Dec 2025 16:25:28 +0100 Subject: [PATCH] Add `Deref` for `Ui` (#7770) * Closes https://github.com/emilk/egui/issues/4033 * Closes https://github.com/emilk/egui/pull/4072 This means you don't have to type `ui.ctx().foo` but just `ui.foo` --------- Co-authored-by: obellish Co-authored-by: obellish <125279760+obellish@users.noreply.github.com> --- crates/egui/src/ui.rs | 128 +++---------------- crates/egui/src/widgets/text_edit/builder.rs | 2 +- 2 files changed, 16 insertions(+), 114 deletions(-) diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 228f2beaf..faede60cf 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -1,34 +1,13 @@ #![warn(missing_docs)] // Let's keep `Ui` well-documented. #![allow(clippy::use_self)] +use std::{any::Any, hash::Hash, ops::Deref, sync::Arc}; + use emath::GuiRounding as _; use epaint::mutex::RwLock; -use epaint::text::FontsView; -use std::{any::Any, hash::Hash, sync::Arc}; -use crate::ClosableTag; -#[cfg(debug_assertions)] -use crate::Stroke; use crate::containers::menu; -use crate::{ - Align, Color32, Context, CursorIcon, DragAndDrop, Id, InnerResponse, InputState, IntoAtoms, - LayerId, Memory, Order, Painter, PlatformOutput, Pos2, Rangef, Rect, Response, Rgba, RichText, - Sense, Style, TextStyle, TextWrapMode, UiBuilder, UiKind, UiStack, UiStackInfo, Vec2, - WidgetRect, WidgetText, - containers::{CollapsingHeader, CollapsingResponse, Frame}, - ecolor::Hsva, - emath, epaint, grid, - layout::{Direction, Layout}, - pass_state, - placer::Placer, - pos2, style, - util::IdTypeMap, - vec2, widgets, - widgets::{ - Button, Checkbox, DragValue, Hyperlink, Image, ImageSource, Label, Link, RadioButton, - Separator, Spinner, TextEdit, Widget, color_picker, - }, -}; +use crate::{containers::*, ecolor::*, layout::*, placer::Placer, widgets::*, *}; // ---------------------------------------------------------------------------- /// This is what you use to place widgets. @@ -112,6 +91,16 @@ pub struct Ui { min_rect_already_remembered: bool, } +/// Allow using [`Ui`] like a [`Context`]. +impl Deref for Ui { + type Target = Context; + + #[inline] + fn deref(&self) -> &Self::Target { + self.ctx() + } +} + impl Ui { // ------------------------------------------------------------------------ // Creation: @@ -459,7 +448,7 @@ impl Ui { &self.style.spacing } - /// Mutably borrow internal [`Spacing`](crate::style::Spacing). + /// Mutably borrow internal [`Spacing`]. /// Changes apply to this [`Ui`] and its subsequent children. /// /// Example: @@ -794,93 +783,6 @@ impl Ui { } } -/// # Helpers for accessing the underlying [`Context`]. -/// These functions all lock the [`Context`] owned by this [`Ui`]. -/// Please see the documentation of [`Context`] for how locking works! -impl Ui { - /// Read-only access to the shared [`InputState`]. - /// - /// ``` - /// # egui::__run_test_ui(|ui| { - /// if ui.input(|i| i.key_pressed(egui::Key::A)) { - /// // … - /// } - /// # }); - /// ``` - #[inline] - pub fn input(&self, reader: impl FnOnce(&InputState) -> R) -> R { - self.ctx().input(reader) - } - - /// Read-write access to the shared [`InputState`]. - #[inline] - pub fn input_mut(&self, writer: impl FnOnce(&mut InputState) -> R) -> R { - self.ctx().input_mut(writer) - } - - /// Read-only access to the shared [`Memory`]. - #[inline] - pub fn memory(&self, reader: impl FnOnce(&Memory) -> R) -> R { - self.ctx().memory(reader) - } - - /// Read-write access to the shared [`Memory`]. - #[inline] - pub fn memory_mut(&self, writer: impl FnOnce(&mut Memory) -> R) -> R { - self.ctx().memory_mut(writer) - } - - /// Read-only access to the shared [`IdTypeMap`], which stores superficial widget state. - #[inline] - pub fn data(&self, reader: impl FnOnce(&IdTypeMap) -> R) -> R { - self.ctx().data(reader) - } - - /// Read-write access to the shared [`IdTypeMap`], which stores superficial widget state. - #[inline] - pub fn data_mut(&self, writer: impl FnOnce(&mut IdTypeMap) -> R) -> R { - self.ctx().data_mut(writer) - } - - /// Read-only access to the shared [`PlatformOutput`]. - /// - /// This is what egui outputs each frame. - /// - /// ``` - /// # let mut ctx = egui::Context::default(); - /// ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Progress); - /// ``` - #[inline] - pub fn output(&self, reader: impl FnOnce(&PlatformOutput) -> R) -> R { - self.ctx().output(reader) - } - - /// Read-write access to the shared [`PlatformOutput`]. - /// - /// This is what egui outputs each frame. - /// - /// ``` - /// # let mut ctx = egui::Context::default(); - /// ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Progress); - /// ``` - #[inline] - pub fn output_mut(&self, writer: impl FnOnce(&mut PlatformOutput) -> R) -> R { - self.ctx().output_mut(writer) - } - - /// Read-only access to [`FontsView`]. - #[inline] - pub fn fonts(&self, reader: impl FnOnce(&FontsView<'_>) -> R) -> R { - self.ctx().fonts(reader) - } - - /// Read-write access to [`FontsView`]. - #[inline] - pub fn fonts_mut(&self, reader: impl FnOnce(&mut FontsView<'_>) -> R) -> R { - self.ctx().fonts_mut(reader) - } -} - // ------------------------------------------------------------------------ /// # Sizes etc @@ -1432,7 +1334,7 @@ impl Ui { crate::StrokeKind::Inside, ); - let stroke = Stroke::new(2.5, Color32::from_rgb(200, 0, 0)); + let stroke = crate::Stroke::new(2.5, Color32::from_rgb(200, 0, 0)); let paint_line_seg = |a, b| self.painter().line_segment([a, b], stroke); if debug_expand_width && too_wide { diff --git a/crates/egui/src/widgets/text_edit/builder.rs b/crates/egui/src/widgets/text_edit/builder.rs index e364b4a00..a9483a722 100644 --- a/crates/egui/src/widgets/text_edit/builder.rs +++ b/crates/egui/src/widgets/text_edit/builder.rs @@ -256,7 +256,7 @@ impl<'t> TextEdit<'t> { /// so it is strongly suggested that you cache the results of any syntax highlighter /// so as not to waste CPU highlighting the same string every frame. /// - /// The arguments is the enclosing [`Ui`] (so you can access e.g. [`Ui::fonts`]), + /// The arguments is the enclosing [`Ui`] (so you can access e.g. [`Context::fonts`]), /// the text and the wrap width. /// /// ```