mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
Remove everything that was marked #[deprecated] (#8105)
Simplify. Streamline. Spring cleaning.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! `epi` provides interfaces for window management and serialization.
|
||||
//!
|
||||
//! Start by looking at the [`App`] trait, and implement [`App::update`].
|
||||
//! Start by looking at the [`App`] trait, and implement [`App::ui`].
|
||||
|
||||
#![warn(missing_docs)] // Let's keep `epi` well-documented.
|
||||
|
||||
@@ -161,22 +161,6 @@ pub trait App {
|
||||
/// (A "viewport" in egui means an native OS window).
|
||||
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut Frame);
|
||||
|
||||
/// Called each time the UI needs repainting, which may be many times per second.
|
||||
///
|
||||
/// Put your widgets into a [`egui::Panel`], [`egui::CentralPanel`], [`egui::Window`] or [`egui::Area`].
|
||||
///
|
||||
/// The [`egui::Context`] can be cloned and saved if you like.
|
||||
///
|
||||
/// To force a repaint, call [`egui::Context::request_repaint`] at any time (e.g. from another thread).
|
||||
///
|
||||
/// This is called for the root viewport ([`egui::ViewportId::ROOT`]).
|
||||
/// Use [`egui::Context::show_viewport_deferred`] to spawn additional viewports (windows).
|
||||
/// (A "viewport" in egui means an native OS window).
|
||||
#[deprecated = "Use Self::ui instead"]
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
|
||||
_ = (ctx, frame);
|
||||
}
|
||||
|
||||
/// Get a handle to the app.
|
||||
///
|
||||
/// Can be used from web to interact or other external context.
|
||||
@@ -256,7 +240,7 @@ pub trait App {
|
||||
true
|
||||
}
|
||||
|
||||
/// A hook for manipulating or filtering raw input before it is processed by [`Self::update`].
|
||||
/// A hook for manipulating or filtering raw input before it is processed by [`Self::ui`].
|
||||
///
|
||||
/// This function provides a way to modify or filter input events before they are processed by egui.
|
||||
///
|
||||
@@ -780,7 +764,7 @@ impl Frame {
|
||||
/// * Read the pixel buffer from the previous frame (`glow::Context::read_pixels`).
|
||||
/// * Render things behind the egui windows.
|
||||
///
|
||||
/// Note that all egui painting is deferred to after the call to [`App::update`]
|
||||
/// Note that all egui painting is deferred to after the call to [`App::ui`]
|
||||
/// ([`egui`] only collects [`egui::Shape`]s and then eframe paints them all in one go later on).
|
||||
///
|
||||
/// To get a [`glow`] context you need to compile with the `glow` feature flag,
|
||||
@@ -886,7 +870,7 @@ pub struct IntegrationInfo {
|
||||
|
||||
/// Seconds of cpu usage (in seconds) on the previous frame.
|
||||
///
|
||||
/// This includes [`App::update`] as well as rendering (except for vsync waiting).
|
||||
/// This includes [`App::ui`] as well as rendering (except for vsync waiting).
|
||||
///
|
||||
/// For a more detailed view of cpu usage, connect your preferred profiler by enabling it's feature in [`profiling`](https://crates.io/crates/profiling).
|
||||
///
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//! To get started, see the [examples](https://github.com/emilk/egui/tree/main/examples).
|
||||
//! To learn how to set up `eframe` for web and native, go to <https://github.com/emilk/eframe_template/> and follow the instructions there!
|
||||
//!
|
||||
//! In short, you implement [`App`] (especially [`App::update`]) and then
|
||||
//! In short, you implement [`App`] (especially [`App::ui`]) and then
|
||||
//! call [`crate::run_native`] from your `main.rs`, and/or use `eframe::WebRunner` from your `lib.rs`.
|
||||
//!
|
||||
//! ## Compiling for web
|
||||
@@ -19,7 +19,7 @@
|
||||
//!
|
||||
//! ## Simplified usage
|
||||
//! If your app is only for native, and you don't need advanced features like state persistence,
|
||||
//! then you can use the simpler function [`run_simple_native`].
|
||||
//! then you can use the simpler function [`run_ui_native`].
|
||||
//!
|
||||
//! ## Usage, native:
|
||||
//! ``` no_run
|
||||
@@ -446,67 +446,6 @@ pub fn run_ui_native(
|
||||
)
|
||||
}
|
||||
|
||||
/// The simplest way to get started when writing a native app.
|
||||
///
|
||||
/// This does NOT support persistence of custom user data. For that you need to use [`run_native`].
|
||||
/// However, it DOES support persistence of egui data (window positions and sizes, how far the user has scrolled in a
|
||||
/// [`ScrollArea`](egui::ScrollArea), etc.) if the persistence feature is enabled.
|
||||
///
|
||||
/// # Example
|
||||
/// ``` no_run
|
||||
/// fn main() -> eframe::Result {
|
||||
/// // Our application state:
|
||||
/// let mut name = "Arthur".to_owned();
|
||||
/// let mut age = 42;
|
||||
///
|
||||
/// let options = eframe::NativeOptions::default();
|
||||
/// eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
||||
/// egui::CentralPanel::default().show(ctx, |ui| {
|
||||
/// ui.heading("My egui Application");
|
||||
/// ui.horizontal(|ui| {
|
||||
/// let name_label = ui.label("Your name: ");
|
||||
/// ui.text_edit_singleline(&mut name)
|
||||
/// .labelled_by(name_label.id);
|
||||
/// });
|
||||
/// ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
||||
/// if ui.button("Increment").clicked() {
|
||||
/// age += 1;
|
||||
/// }
|
||||
/// ui.label(format!("Hello '{name}', age {age}"));
|
||||
/// });
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Errors
|
||||
/// This function can fail if we fail to set up a graphics context.
|
||||
#[deprecated = "Use run_ui_native instead"]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
|
||||
pub fn run_simple_native(
|
||||
app_name: &str,
|
||||
native_options: NativeOptions,
|
||||
update_fun: impl FnMut(&egui::Context, &mut Frame) + 'static,
|
||||
) -> Result {
|
||||
struct SimpleApp<U> {
|
||||
update_fun: U,
|
||||
}
|
||||
|
||||
impl<U: FnMut(&egui::Context, &mut Frame) + 'static> App for SimpleApp<U> {
|
||||
fn ui(&mut self, _ui: &mut egui::Ui, _frame: &mut Frame) {}
|
||||
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
|
||||
(self.update_fun)(ctx, frame);
|
||||
}
|
||||
}
|
||||
|
||||
run_native(
|
||||
app_name,
|
||||
native_options,
|
||||
Box::new(|_cc| Ok(Box::new(SimpleApp { update_fun }))),
|
||||
)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// The different problems that can occur when trying to run `eframe`.
|
||||
|
||||
@@ -259,7 +259,7 @@ impl EpiIntegration {
|
||||
|
||||
/// Run user code - this can create immediate viewports, so hold no locks over this!
|
||||
///
|
||||
/// If `viewport_ui_cb` is None, we are in the root viewport and will call [`crate::App::update`].
|
||||
/// If `viewport_ui_cb` is None, we are in the root viewport and will call [`crate::App::ui`].
|
||||
pub fn update(
|
||||
&mut self,
|
||||
app: &mut dyn epi::App,
|
||||
@@ -287,12 +287,6 @@ impl EpiIntegration {
|
||||
}
|
||||
|
||||
if is_visible {
|
||||
{
|
||||
profiling::scope!("App::update");
|
||||
#[expect(deprecated)]
|
||||
app.update(ui.ctx(), &mut self.frame);
|
||||
}
|
||||
|
||||
{
|
||||
profiling::scope!("App::ui");
|
||||
app.ui(ui, &mut self.frame);
|
||||
|
||||
@@ -284,9 +284,6 @@ impl AppRunner {
|
||||
self.app.logic(ui.ctx(), &mut self.frame);
|
||||
|
||||
if is_visible {
|
||||
#[expect(deprecated)]
|
||||
self.app.update(ui.ctx(), &mut self.frame);
|
||||
|
||||
self.app.ui(ui, &mut self.frame);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -280,7 +280,7 @@ impl Area {
|
||||
self
|
||||
}
|
||||
|
||||
/// Constrains this area to [`Context::screen_rect`]?
|
||||
/// Constrains this area to [`Context::content_rect`]?
|
||||
///
|
||||
/// Default: `true`.
|
||||
#[inline]
|
||||
@@ -291,7 +291,7 @@ impl Area {
|
||||
|
||||
/// Constrain the movement of the window to the given rectangle.
|
||||
///
|
||||
/// For instance: `.constrain_to(ctx.screen_rect())`.
|
||||
/// For instance: `.constrain_to(ctx.content_rect())`.
|
||||
#[inline]
|
||||
pub fn constrain_to(mut self, constrain_rect: Rect) -> Self {
|
||||
self.constrain = true;
|
||||
|
||||
@@ -451,15 +451,6 @@ impl CollapsingHeader {
|
||||
self
|
||||
}
|
||||
|
||||
/// Explicitly set the source of the [`Id`] of this widget, instead of using title label.
|
||||
/// This is useful if the title label is dynamic or not unique.
|
||||
#[deprecated = "Renamed id_salt"]
|
||||
#[inline]
|
||||
pub fn id_source(mut self, id_salt: impl Hash) -> Self {
|
||||
self.id_salt = Id::new(id_salt);
|
||||
self
|
||||
}
|
||||
|
||||
/// If you set this to `false`, the [`CollapsingHeader`] will be grayed out and un-clickable.
|
||||
///
|
||||
/// This is a convenience for [`Ui::disable`].
|
||||
|
||||
@@ -94,12 +94,6 @@ impl ComboBox {
|
||||
}
|
||||
}
|
||||
|
||||
/// Without label.
|
||||
#[deprecated = "Renamed from_id_salt"]
|
||||
pub fn from_id_source(id_salt: impl std::hash::Hash) -> Self {
|
||||
Self::from_id_salt(id_salt)
|
||||
}
|
||||
|
||||
/// Set the outer width of the button and menu.
|
||||
///
|
||||
/// Default is [`Spacing::combo_width`].
|
||||
|
||||
@@ -174,11 +174,6 @@ impl Frame {
|
||||
Self::NONE
|
||||
}
|
||||
|
||||
#[deprecated = "Use `Frame::NONE` or `Frame::new()` instead."]
|
||||
pub const fn none() -> Self {
|
||||
Self::NONE
|
||||
}
|
||||
|
||||
/// For when you want to group a few widgets together within a frame.
|
||||
pub fn group(style: &Style) -> Self {
|
||||
Self::new()
|
||||
@@ -283,16 +278,6 @@ impl Frame {
|
||||
self
|
||||
}
|
||||
|
||||
/// The rounding of the _outer_ corner of the [`Self::stroke`]
|
||||
/// (or, if there is no stroke, the outer corner of [`Self::fill`]).
|
||||
///
|
||||
/// In other words, this is the corner radius of the _widget rect_.
|
||||
#[inline]
|
||||
#[deprecated = "Renamed to `corner_radius`"]
|
||||
pub fn rounding(self, corner_radius: impl Into<CornerRadius>) -> Self {
|
||||
self.corner_radius(corner_radius)
|
||||
}
|
||||
|
||||
/// Margin outside the painted frame.
|
||||
///
|
||||
/// Similar to what is called `margin` in CSS.
|
||||
|
||||
@@ -197,7 +197,7 @@ impl MenuState {
|
||||
|
||||
/// Horizontal menu bar where you can add [`MenuButton`]s.
|
||||
///
|
||||
/// The menu bar goes well in a [`crate::TopBottomPanel::top`],
|
||||
/// The menu bar goes well in a [`crate::Panel::top`],
|
||||
/// but can also be placed in a [`crate::Window`].
|
||||
/// In the latter case you may want to wrap it in [`Frame`].
|
||||
///
|
||||
@@ -219,9 +219,6 @@ pub struct MenuBar {
|
||||
style: StyleModifier,
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed to `egui::MenuBar`"]
|
||||
pub type Bar = MenuBar;
|
||||
|
||||
impl Default for MenuBar {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -9,7 +9,6 @@ mod combo_box;
|
||||
pub mod frame;
|
||||
pub mod menu;
|
||||
pub mod modal;
|
||||
pub mod old_popup;
|
||||
pub mod panel;
|
||||
mod popup;
|
||||
pub(crate) mod resize;
|
||||
@@ -26,7 +25,6 @@ pub use {
|
||||
combo_box::*,
|
||||
frame::Frame,
|
||||
modal::{Modal, ModalResponse},
|
||||
old_popup::*,
|
||||
panel::*,
|
||||
popup::*,
|
||||
resize::Resize,
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
//! Old and deprecated API for popups. Use [`Popup`] instead.
|
||||
#![expect(deprecated)]
|
||||
|
||||
use crate::containers::tooltip::Tooltip;
|
||||
use crate::{
|
||||
Align, Context, Id, LayerId, Layout, Popup, PopupAnchor, PopupCloseBehavior, Pos2, Rect,
|
||||
Response, Ui, Widget as _, WidgetText,
|
||||
};
|
||||
use emath::RectAlign;
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Show a tooltip at the current pointer position (if any).
|
||||
///
|
||||
/// Most of the time it is easier to use [`Response::on_hover_ui`].
|
||||
///
|
||||
/// See also [`show_tooltip_text`].
|
||||
///
|
||||
/// Returns `None` if the tooltip could not be placed.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// # #[expect(deprecated)]
|
||||
/// if ui.ui_contains_pointer() {
|
||||
/// egui::show_tooltip(ui.ctx(), ui.layer_id(), egui::Id::new("my_tooltip"), |ui| {
|
||||
/// ui.label("Helpful text");
|
||||
/// });
|
||||
/// }
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use `egui::Tooltip` instead"]
|
||||
pub fn show_tooltip<R>(
|
||||
ctx: &Context,
|
||||
parent_layer: LayerId,
|
||||
widget_id: Id,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
show_tooltip_at_pointer(ctx, parent_layer, widget_id, add_contents)
|
||||
}
|
||||
|
||||
/// Show a tooltip at the current pointer position (if any).
|
||||
///
|
||||
/// Most of the time it is easier to use [`Response::on_hover_ui`].
|
||||
///
|
||||
/// See also [`show_tooltip_text`].
|
||||
///
|
||||
/// Returns `None` if the tooltip could not be placed.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// if ui.ui_contains_pointer() {
|
||||
/// egui::show_tooltip_at_pointer(ui.ctx(), ui.layer_id(), egui::Id::new("my_tooltip"), |ui| {
|
||||
/// ui.label("Helpful text");
|
||||
/// });
|
||||
/// }
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use `egui::Tooltip` instead"]
|
||||
pub fn show_tooltip_at_pointer<R>(
|
||||
ctx: &Context,
|
||||
parent_layer: LayerId,
|
||||
widget_id: Id,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
Tooltip::always_open(ctx.clone(), parent_layer, widget_id, PopupAnchor::Pointer)
|
||||
.gap(12.0)
|
||||
.show(add_contents)
|
||||
.map(|response| response.inner)
|
||||
}
|
||||
|
||||
/// Show a tooltip under the given area.
|
||||
///
|
||||
/// If the tooltip does not fit under the area, it tries to place it above it instead.
|
||||
#[deprecated = "Use `egui::Tooltip` instead"]
|
||||
pub fn show_tooltip_for<R>(
|
||||
ctx: &Context,
|
||||
parent_layer: LayerId,
|
||||
widget_id: Id,
|
||||
widget_rect: &Rect,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
Tooltip::always_open(ctx.clone(), parent_layer, widget_id, *widget_rect)
|
||||
.show(add_contents)
|
||||
.map(|response| response.inner)
|
||||
}
|
||||
|
||||
/// Show a tooltip at the given position.
|
||||
///
|
||||
/// Returns `None` if the tooltip could not be placed.
|
||||
#[deprecated = "Use `egui::Tooltip` instead"]
|
||||
pub fn show_tooltip_at<R>(
|
||||
ctx: &Context,
|
||||
parent_layer: LayerId,
|
||||
widget_id: Id,
|
||||
suggested_position: Pos2,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
Tooltip::always_open(ctx.clone(), parent_layer, widget_id, suggested_position)
|
||||
.show(add_contents)
|
||||
.map(|response| response.inner)
|
||||
}
|
||||
|
||||
/// Show some text at the current pointer position (if any).
|
||||
///
|
||||
/// Most of the time it is easier to use [`Response::on_hover_text`].
|
||||
///
|
||||
/// See also [`show_tooltip`].
|
||||
///
|
||||
/// Returns `None` if the tooltip could not be placed.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// if ui.ui_contains_pointer() {
|
||||
/// egui::show_tooltip_text(ui.ctx(), ui.layer_id(), egui::Id::new("my_tooltip"), "Helpful text");
|
||||
/// }
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use `egui::Tooltip` instead"]
|
||||
pub fn show_tooltip_text(
|
||||
ctx: &Context,
|
||||
parent_layer: LayerId,
|
||||
widget_id: Id,
|
||||
text: impl Into<WidgetText>,
|
||||
) -> Option<()> {
|
||||
show_tooltip(ctx, parent_layer, widget_id, |ui| {
|
||||
crate::widgets::Label::new(text).ui(ui);
|
||||
})
|
||||
}
|
||||
|
||||
/// Was this tooltip visible last frame?
|
||||
#[deprecated = "Use `Tooltip::was_tooltip_open_last_frame` instead"]
|
||||
pub fn was_tooltip_open_last_frame(ctx: &Context, widget_id: Id) -> bool {
|
||||
Tooltip::was_tooltip_open_last_frame(ctx, widget_id)
|
||||
}
|
||||
|
||||
/// Indicate whether a popup will be shown above or below the box.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum AboveOrBelow {
|
||||
Above,
|
||||
Below,
|
||||
}
|
||||
|
||||
/// Helper for [`popup_above_or_below_widget`].
|
||||
#[deprecated = "Use `egui::Popup` instead"]
|
||||
pub fn popup_below_widget<R>(
|
||||
ui: &Ui,
|
||||
popup_id: Id,
|
||||
widget_response: &Response,
|
||||
close_behavior: PopupCloseBehavior,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
popup_above_or_below_widget(
|
||||
ui,
|
||||
popup_id,
|
||||
widget_response,
|
||||
AboveOrBelow::Below,
|
||||
close_behavior,
|
||||
add_contents,
|
||||
)
|
||||
}
|
||||
|
||||
/// Shows a popup above or below another widget.
|
||||
///
|
||||
/// Useful for drop-down menus (combo boxes) or suggestion menus under text fields.
|
||||
///
|
||||
/// The opened popup will have a minimum width matching its parent.
|
||||
///
|
||||
/// You must open the popup with [`crate::Memory::open_popup`] or [`crate::Memory::toggle_popup`].
|
||||
///
|
||||
/// Returns `None` if the popup is not open.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// let response = ui.button("Open popup");
|
||||
/// let popup_id = ui.make_persistent_id("my_unique_id");
|
||||
/// if response.clicked() {
|
||||
/// ui.memory_mut(|mem| mem.toggle_popup(popup_id));
|
||||
/// }
|
||||
/// let below = egui::AboveOrBelow::Below;
|
||||
/// let close_on_click_outside = egui::PopupCloseBehavior::CloseOnClickOutside;
|
||||
/// # #[expect(deprecated)]
|
||||
/// egui::popup_above_or_below_widget(ui, popup_id, &response, below, close_on_click_outside, |ui| {
|
||||
/// ui.set_min_width(200.0); // if you want to control the size
|
||||
/// ui.label("Some more info, or things you can select:");
|
||||
/// ui.label("…");
|
||||
/// });
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use `egui::Popup` instead"]
|
||||
pub fn popup_above_or_below_widget<R>(
|
||||
_parent_ui: &Ui,
|
||||
popup_id: Id,
|
||||
widget_response: &Response,
|
||||
above_or_below: AboveOrBelow,
|
||||
close_behavior: PopupCloseBehavior,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
let response = Popup::from_response(widget_response)
|
||||
.layout(Layout::top_down_justified(Align::LEFT))
|
||||
.open_memory(None)
|
||||
.close_behavior(close_behavior)
|
||||
.id(popup_id)
|
||||
.align(match above_or_below {
|
||||
AboveOrBelow::Above => RectAlign::TOP_START,
|
||||
AboveOrBelow::Below => RectAlign::BOTTOM_START,
|
||||
})
|
||||
.width(widget_response.rect.width())
|
||||
.show(|ui| {
|
||||
ui.set_min_width(ui.available_width());
|
||||
add_contents(ui)
|
||||
})?;
|
||||
Some(response.inner)
|
||||
}
|
||||
@@ -18,9 +18,8 @@
|
||||
use emath::{GuiRounding as _, Pos2};
|
||||
|
||||
use crate::{
|
||||
Align, Context, CursorIcon, Frame, Id, InnerResponse, LayerId, Layout, NumExt as _, Rangef,
|
||||
Rect, Sense, Stroke, Ui, UiBuilder, UiKind, UiStackInfo, Vec2, WidgetInfo, WidgetType, lerp,
|
||||
vec2,
|
||||
Align, Context, CursorIcon, Frame, Id, InnerResponse, Layout, NumExt as _, Rangef, Rect, Sense,
|
||||
Stroke, Ui, UiBuilder, UiKind, UiStackInfo, Vec2, lerp, vec2,
|
||||
};
|
||||
|
||||
fn animate_expansion(ctx: &Context, id: Id, is_expanded: bool) -> f32 {
|
||||
@@ -451,59 +450,6 @@ impl Panel {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
impl Panel {
|
||||
#[deprecated = "Renamed default_size"]
|
||||
pub fn default_width(self, default_size: f32) -> Self {
|
||||
self.default_size(default_size)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed min_size"]
|
||||
pub fn min_width(self, min_size: f32) -> Self {
|
||||
self.min_size(min_size)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed max_size"]
|
||||
pub fn max_width(self, max_size: f32) -> Self {
|
||||
self.max_size(max_size)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed size_range"]
|
||||
pub fn width_range(self, size_range: impl Into<Rangef>) -> Self {
|
||||
self.size_range(size_range)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed exact_size"]
|
||||
pub fn exact_width(self, size: f32) -> Self {
|
||||
self.exact_size(size)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed default_size"]
|
||||
pub fn default_height(self, default_size: f32) -> Self {
|
||||
self.default_size(default_size)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed min_size"]
|
||||
pub fn min_height(self, min_size: f32) -> Self {
|
||||
self.min_size(min_size)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed max_size"]
|
||||
pub fn max_height(self, max_size: f32) -> Self {
|
||||
self.max_size(max_size)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed size_range"]
|
||||
pub fn height_range(self, size_range: impl Into<Rangef>) -> Self {
|
||||
self.size_range(size_range)
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed exact_size"]
|
||||
pub fn exact_height(self, size: f32) -> Self {
|
||||
self.exact_size(size)
|
||||
}
|
||||
}
|
||||
|
||||
// Public showing methods
|
||||
impl Panel {
|
||||
/// Show the panel inside a [`Ui`].
|
||||
@@ -515,41 +461,6 @@ impl Panel {
|
||||
self.show_inside_dyn(ui, Box::new(add_contents))
|
||||
}
|
||||
|
||||
/// Show the panel at the top level.
|
||||
#[deprecated = "Use show_inside() instead"]
|
||||
pub fn show<R>(
|
||||
self,
|
||||
ctx: &Context,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
self.show_dyn(ctx, Box::new(add_contents))
|
||||
}
|
||||
|
||||
/// Show the panel if `is_expanded` is `true`,
|
||||
/// otherwise don't show it, but with a nice animation between collapsed and expanded.
|
||||
#[deprecated = "Use show_animated_inside() instead"]
|
||||
pub fn show_animated<R>(
|
||||
self,
|
||||
ctx: &Context,
|
||||
is_expanded: bool,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<InnerResponse<R>> {
|
||||
#![expect(deprecated)]
|
||||
|
||||
let how_expanded = animate_expansion(ctx, self.id.with("animation"), is_expanded);
|
||||
|
||||
let animated_panel = self.get_animated_panel(ctx, is_expanded)?;
|
||||
|
||||
if how_expanded < 1.0 {
|
||||
// Show a fake panel in this in-between animation state:
|
||||
animated_panel.show(ctx, |_ui| {});
|
||||
None
|
||||
} else {
|
||||
// Show the real panel:
|
||||
Some(animated_panel.show(ctx, add_contents))
|
||||
}
|
||||
}
|
||||
|
||||
/// Show the panel if `is_expanded` is `true`,
|
||||
/// otherwise don't show it, but with a nice animation between collapsed and expanded.
|
||||
pub fn show_animated_inside<R>(
|
||||
@@ -577,34 +488,6 @@ impl Panel {
|
||||
}
|
||||
}
|
||||
|
||||
/// Show either a collapsed or a expanded panel, with a nice animation between.
|
||||
#[deprecated = "Use show_animated_between_inside() instead"]
|
||||
pub fn show_animated_between<R>(
|
||||
ctx: &Context,
|
||||
is_expanded: bool,
|
||||
collapsed_panel: Self,
|
||||
expanded_panel: Self,
|
||||
add_contents: impl FnOnce(&mut Ui, f32) -> R,
|
||||
) -> Option<InnerResponse<R>> {
|
||||
#![expect(deprecated)]
|
||||
|
||||
let how_expanded = animate_expansion(ctx, expanded_panel.id.with("animation"), is_expanded);
|
||||
|
||||
// Get either the fake or the real panel to animate
|
||||
let animated_between_panel =
|
||||
Self::get_animated_between_panel(ctx, is_expanded, collapsed_panel, expanded_panel);
|
||||
|
||||
if 0.0 == how_expanded {
|
||||
Some(animated_between_panel.show(ctx, |ui| add_contents(ui, how_expanded)))
|
||||
} else if how_expanded < 1.0 {
|
||||
// Show animation:
|
||||
animated_between_panel.show(ctx, |ui| add_contents(ui, how_expanded));
|
||||
None
|
||||
} else {
|
||||
Some(animated_between_panel.show(ctx, |ui| add_contents(ui, how_expanded)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Show either a collapsed or a expanded panel, with a nice animation between.
|
||||
pub fn show_animated_between_inside<R>(
|
||||
ui: &mut Ui,
|
||||
@@ -756,59 +639,6 @@ impl Panel {
|
||||
inner_response
|
||||
}
|
||||
|
||||
/// Show the panel at the top level.
|
||||
fn show_dyn<'c, R>(
|
||||
self,
|
||||
ctx: &Context,
|
||||
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||
) -> InnerResponse<R> {
|
||||
#![expect(deprecated)]
|
||||
|
||||
let side = self.side;
|
||||
let available_rect = ctx.available_rect();
|
||||
let mut panel_ui = Ui::new(
|
||||
ctx.clone(),
|
||||
self.id,
|
||||
UiBuilder::new()
|
||||
.layer_id(LayerId::background())
|
||||
.max_rect(available_rect),
|
||||
);
|
||||
panel_ui.set_clip_rect(ctx.content_rect());
|
||||
panel_ui
|
||||
.response()
|
||||
.widget_info(|| WidgetInfo::new(WidgetType::Panel));
|
||||
|
||||
let inner_response = self.show_inside_dyn(&mut panel_ui, add_contents);
|
||||
let rect = inner_response.response.rect;
|
||||
|
||||
match side {
|
||||
PanelSide::Vertical(side) => match side {
|
||||
VerticalSide::Left => ctx.pass_state_mut(|state| {
|
||||
state.allocate_left_panel(Rect::from_min_max(available_rect.min, rect.max));
|
||||
}),
|
||||
VerticalSide::Right => ctx.pass_state_mut(|state| {
|
||||
state.allocate_right_panel(Rect::from_min_max(rect.min, available_rect.max));
|
||||
}),
|
||||
},
|
||||
PanelSide::Horizontal(side) => match side {
|
||||
HorizontalSide::Top => {
|
||||
ctx.pass_state_mut(|state| {
|
||||
state.allocate_top_panel(Rect::from_min_max(available_rect.min, rect.max));
|
||||
});
|
||||
}
|
||||
HorizontalSide::Bottom => {
|
||||
ctx.pass_state_mut(|state| {
|
||||
state.allocate_bottom_panel(Rect::from_min_max(
|
||||
rect.min,
|
||||
available_rect.max,
|
||||
));
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
inner_response
|
||||
}
|
||||
|
||||
fn prepare_resizable_panel(&self, panel_sizer: &mut PanelSizer<'_>, ui: &Ui) {
|
||||
let resize_id = self.id.with("__resize");
|
||||
let resize_response = ui.ctx().read_response(resize_id);
|
||||
@@ -1044,61 +874,9 @@ impl CentralPanel {
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
/// Show the panel at the top level.
|
||||
#[deprecated = "Use show_inside() instead"]
|
||||
pub fn show<R>(
|
||||
self,
|
||||
ctx: &Context,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
self.show_dyn(ctx, Box::new(add_contents))
|
||||
}
|
||||
|
||||
/// Show the panel at the top level.
|
||||
fn show_dyn<'c, R>(
|
||||
self,
|
||||
ctx: &Context,
|
||||
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||
) -> InnerResponse<R> {
|
||||
#![expect(deprecated)]
|
||||
|
||||
let id = Id::new((ctx.viewport_id(), "central_panel"));
|
||||
|
||||
let mut panel_ui = Ui::new(
|
||||
ctx.clone(),
|
||||
id,
|
||||
UiBuilder::new()
|
||||
.layer_id(LayerId::background())
|
||||
.max_rect(ctx.available_rect()),
|
||||
);
|
||||
panel_ui.set_clip_rect(ctx.content_rect());
|
||||
|
||||
if false {
|
||||
// TODO(emilk): @lucasmerlin shouldn't we enable this?
|
||||
panel_ui
|
||||
.response()
|
||||
.widget_info(|| WidgetInfo::new(WidgetType::Panel));
|
||||
}
|
||||
|
||||
let inner_response = self.show_inside_dyn(&mut panel_ui, add_contents);
|
||||
|
||||
// Only inform ctx about what we actually used, so we can shrink the native window to fit.
|
||||
ctx.pass_state_mut(|state| state.allocate_central_panel(inner_response.response.rect));
|
||||
|
||||
inner_response
|
||||
}
|
||||
}
|
||||
|
||||
fn clamp_to_range(x: f32, range: Rangef) -> f32 {
|
||||
let range = range.as_positive();
|
||||
x.clamp(range.min, range.max)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[deprecated = "Use Panel::left or Panel::right instead"]
|
||||
pub type SidePanel = super::Panel;
|
||||
|
||||
#[deprecated = "Use Panel::top or Panel::bottom instead"]
|
||||
pub type TopBottomPanel = super::Panel;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#![expect(deprecated)] // This is a new, safe wrapper around the old `Memory::popup` API.
|
||||
|
||||
use std::iter::once;
|
||||
|
||||
use emath::{Align, Pos2, Rect, RectAlign, Vec2, vec2};
|
||||
@@ -87,7 +85,7 @@ pub enum PopupCloseBehavior {
|
||||
/// but in the popup's body
|
||||
CloseOnClickOutside,
|
||||
|
||||
/// Clicks will be ignored. Popup might be closed manually by calling [`crate::Memory::close_all_popups`]
|
||||
/// Clicks will be ignored. Popup might be closed manually by calling [`Popup::close_all`]
|
||||
/// or by pressing the escape button
|
||||
IgnoreClicks,
|
||||
}
|
||||
@@ -666,10 +664,6 @@ impl Popup<'_> {
|
||||
}
|
||||
|
||||
/// Open the given popup and close all others.
|
||||
///
|
||||
/// If you are NOT using [`Popup::show`], you must
|
||||
/// also call [`crate::Memory::keep_popup_open`] as long as
|
||||
/// you're showing the popup.
|
||||
pub fn open_id(ctx: &Context, popup_id: Id) {
|
||||
ctx.memory_mut(|mem| mem.open_popup(popup_id));
|
||||
}
|
||||
|
||||
@@ -69,13 +69,6 @@ impl Resize {
|
||||
self
|
||||
}
|
||||
|
||||
/// A source for the unique [`Id`], e.g. `.id_source("second_resize_area")` or `.id_source(loop_index)`.
|
||||
#[inline]
|
||||
#[deprecated = "Renamed id_salt"]
|
||||
pub fn id_source(self, id_salt: impl std::hash::Hash) -> Self {
|
||||
self.id_salt(id_salt)
|
||||
}
|
||||
|
||||
/// A source for the unique [`Id`], e.g. `.id_salt("second_resize_area")` or `.id_salt(loop_index)`.
|
||||
#[inline]
|
||||
pub fn id_salt(mut self, id_salt: impl std::hash::Hash) -> Self {
|
||||
|
||||
@@ -423,13 +423,6 @@ impl ScrollArea {
|
||||
self
|
||||
}
|
||||
|
||||
/// A source for the unique [`Id`], e.g. `.id_source("second_scroll_area")` or `.id_source(loop_index)`.
|
||||
#[inline]
|
||||
#[deprecated = "Renamed id_salt"]
|
||||
pub fn id_source(self, id_salt: impl std::hash::Hash) -> Self {
|
||||
self.id_salt(id_salt)
|
||||
}
|
||||
|
||||
/// A source for the unique [`Id`], e.g. `.id_salt("second_scroll_area")` or `.id_salt(loop_index)`.
|
||||
#[inline]
|
||||
pub fn id_salt(mut self, id_salt: impl std::hash::Hash) -> Self {
|
||||
@@ -530,32 +523,6 @@ impl ScrollArea {
|
||||
/// This can be used, for example, to optionally freeze scrolling while the user
|
||||
/// is typing text in a [`crate::TextEdit`] widget contained within the scroll area.
|
||||
///
|
||||
/// This controls both scrolling directions.
|
||||
#[deprecated = "Use `ScrollArea::scroll_source()"]
|
||||
#[inline]
|
||||
pub fn enable_scrolling(mut self, enable: bool) -> Self {
|
||||
self.scroll_source = if enable {
|
||||
ScrollSource::ALL
|
||||
} else {
|
||||
ScrollSource::NONE
|
||||
};
|
||||
self
|
||||
}
|
||||
|
||||
/// Can the user drag the scroll area to scroll?
|
||||
///
|
||||
/// This is useful for touch screens.
|
||||
///
|
||||
/// If `true`, the [`ScrollArea`] will sense drags.
|
||||
///
|
||||
/// Default: `true`.
|
||||
#[deprecated = "Use `ScrollArea::scroll_source()"]
|
||||
#[inline]
|
||||
pub fn drag_to_scroll(mut self, drag_to_scroll: bool) -> Self {
|
||||
self.scroll_source.drag = drag_to_scroll;
|
||||
self
|
||||
}
|
||||
|
||||
/// What sources does the [`ScrollArea`] use for scrolling the contents.
|
||||
#[inline]
|
||||
pub fn scroll_source(mut self, scroll_source: ScrollSource) -> Self {
|
||||
|
||||
@@ -16,24 +16,6 @@ pub struct Tooltip<'a> {
|
||||
}
|
||||
|
||||
impl Tooltip<'_> {
|
||||
/// Show a tooltip that is always open.
|
||||
#[deprecated = "Use `Tooltip::always_open` instead."]
|
||||
pub fn new(
|
||||
parent_widget: Id,
|
||||
ctx: Context,
|
||||
anchor: impl Into<PopupAnchor>,
|
||||
parent_layer: LayerId,
|
||||
) -> Self {
|
||||
Self {
|
||||
popup: Popup::new(parent_widget, ctx, anchor.into(), parent_layer)
|
||||
.kind(PopupKind::Tooltip)
|
||||
.gap(4.0)
|
||||
.sense(Sense::hover()),
|
||||
parent_layer,
|
||||
parent_widget,
|
||||
}
|
||||
}
|
||||
|
||||
/// Show a tooltip that is always open.
|
||||
pub fn always_open(
|
||||
ctx: Context,
|
||||
|
||||
@@ -262,7 +262,7 @@ impl<'open> Window<'open> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Constrains this window to [`Context::screen_rect`].
|
||||
/// Constrains this window to [`Context::content_rect`].
|
||||
///
|
||||
/// To change the area to constrain to, use [`Self::constrain_to`].
|
||||
///
|
||||
@@ -275,7 +275,7 @@ impl<'open> Window<'open> {
|
||||
|
||||
/// Constrain the movement of the window to the given rectangle.
|
||||
///
|
||||
/// For instance: `.constrain_to(ctx.screen_rect())`.
|
||||
/// For instance: `.constrain_to(ctx.content_rect())`.
|
||||
#[inline]
|
||||
pub fn constrain_to(mut self, constrain_rect: Rect) -> Self {
|
||||
self.area = self.area.constrain_to(constrain_rect);
|
||||
@@ -427,7 +427,7 @@ impl<'open> Window<'open> {
|
||||
|
||||
/// Enable/disable scrolling on the window by dragging with the pointer. `true` by default.
|
||||
///
|
||||
/// See [`ScrollArea::drag_to_scroll`] for more.
|
||||
/// See [`ScrollArea::scroll_source`] for more.
|
||||
#[inline]
|
||||
pub fn drag_to_scroll(mut self, drag_to_scroll: bool) -> Self {
|
||||
self.scroll = self.scroll.scroll_source(ScrollSource {
|
||||
|
||||
@@ -300,7 +300,7 @@ impl RepaintCause {
|
||||
struct ViewportRepaintInfo {
|
||||
/// Monotonically increasing counter.
|
||||
///
|
||||
/// Incremented at the end of [`Context::run`].
|
||||
/// Incremented at the end of [`Context::run_ui`].
|
||||
/// This can be smaller than [`Self::cumulative_pass_nr`],
|
||||
/// but never larger.
|
||||
cumulative_frame_nr: u64,
|
||||
@@ -463,7 +463,7 @@ impl ContextImpl {
|
||||
|
||||
let content_rect = viewport.input.content_rect();
|
||||
|
||||
viewport.this_pass.begin_pass(content_rect);
|
||||
viewport.this_pass.begin_pass();
|
||||
|
||||
{
|
||||
let mut layers: Vec<LayerId> = viewport.prev_pass.widgets.layer_ids().collect();
|
||||
@@ -697,8 +697,8 @@ impl ContextImpl {
|
||||
/// // Game loop:
|
||||
/// loop {
|
||||
/// let raw_input = egui::RawInput::default();
|
||||
/// let full_output = ctx.run(raw_input, |ctx| {
|
||||
/// egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
/// let full_output = ctx.run_ui(raw_input, |ui| {
|
||||
/// egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
/// ui.label("Hello world!");
|
||||
/// if ui.button("Click me").clicked() {
|
||||
/// // take some action here
|
||||
@@ -780,9 +780,6 @@ impl Context {
|
||||
/// });
|
||||
/// // handle full_output
|
||||
/// ```
|
||||
///
|
||||
/// ## See also
|
||||
/// * [`Self::run`]
|
||||
#[must_use]
|
||||
pub fn run_ui(&self, new_input: RawInput, mut run_ui: impl FnMut(&mut Ui)) -> FullOutput {
|
||||
self.run_ui_dyn(new_input, &mut run_ui)
|
||||
@@ -791,14 +788,13 @@ impl Context {
|
||||
#[must_use]
|
||||
fn run_ui_dyn(&self, new_input: RawInput, run_ui: &mut dyn FnMut(&mut Ui)) -> FullOutput {
|
||||
let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
|
||||
#[expect(deprecated)]
|
||||
self.run(new_input, |ctx| {
|
||||
self.run_dyn(new_input, &mut |ctx| {
|
||||
let mut root_ui = Ui::new(
|
||||
ctx.clone(),
|
||||
Id::new((ctx.viewport_id(), "__top_ui")),
|
||||
UiBuilder::new()
|
||||
.layer_id(LayerId::background())
|
||||
.max_rect(ctx.available_rect()),
|
||||
.max_rect(ctx.viewport_rect()),
|
||||
);
|
||||
|
||||
{
|
||||
@@ -814,38 +810,6 @@ impl Context {
|
||||
})
|
||||
}
|
||||
|
||||
/// Run the ui code for one frame.
|
||||
///
|
||||
/// At most [`Options::max_passes`] calls will be issued to `run_ui`,
|
||||
/// and only on the rare occasion that [`Context::request_discard`] is called.
|
||||
/// Usually, it `run_ui` will only be called once.
|
||||
///
|
||||
/// Put your widgets into a [`crate::Panel`], [`crate::CentralPanel`], [`crate::Window`] or [`crate::Area`].
|
||||
///
|
||||
/// Instead of calling `run`, you can alternatively use [`Self::begin_pass`] and [`Context::end_pass`].
|
||||
///
|
||||
/// ```
|
||||
/// // One egui context that you keep reusing:
|
||||
/// let mut ctx = egui::Context::default();
|
||||
///
|
||||
/// // Each frame:
|
||||
/// let input = egui::RawInput::default();
|
||||
/// let full_output = ctx.run(input, |ctx| {
|
||||
/// egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
/// ui.label("Hello egui!");
|
||||
/// });
|
||||
/// });
|
||||
/// // handle full_output
|
||||
/// ```
|
||||
///
|
||||
/// ## See also
|
||||
/// * [`Self::run_ui`]
|
||||
#[must_use]
|
||||
#[deprecated = "Call run_ui instead"]
|
||||
pub fn run(&self, new_input: RawInput, mut run_ui: impl FnMut(&Self)) -> FullOutput {
|
||||
self.run_dyn(new_input, &mut run_ui)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn run_dyn(&self, mut new_input: RawInput, run_ui: &mut dyn FnMut(&Self)) -> FullOutput {
|
||||
profiling::function_scope!();
|
||||
@@ -915,10 +879,10 @@ impl Context {
|
||||
output
|
||||
}
|
||||
|
||||
/// An alternative to calling [`Self::run`].
|
||||
/// An alternative to calling [`Self::run_ui`].
|
||||
///
|
||||
/// It is usually better to use [`Self::run`], because
|
||||
/// `run` supports multi-pass layout using [`Self::request_discard`].
|
||||
/// It is usually better to use [`Self::run_ui`], because
|
||||
/// `run_ui` supports multi-pass layout using [`Self::request_discard`].
|
||||
///
|
||||
/// ```
|
||||
/// // One egui context that you keep reusing:
|
||||
@@ -928,9 +892,7 @@ impl Context {
|
||||
/// let input = egui::RawInput::default();
|
||||
/// ctx.begin_pass(input);
|
||||
///
|
||||
/// egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
/// ui.label("Hello egui!");
|
||||
/// });
|
||||
/// // … add panels and windows here …
|
||||
///
|
||||
/// let full_output = ctx.end_pass();
|
||||
/// // handle full_output
|
||||
@@ -943,12 +905,6 @@ impl Context {
|
||||
|
||||
self.write(|ctx| ctx.begin_pass(new_input));
|
||||
}
|
||||
|
||||
/// See [`Self::begin_pass`].
|
||||
#[deprecated = "Renamed begin_pass"]
|
||||
pub fn begin_frame(&self, new_input: RawInput) {
|
||||
self.begin_pass(new_input);
|
||||
}
|
||||
}
|
||||
|
||||
/// ## Borrows parts of [`Context`]
|
||||
@@ -1049,7 +1005,7 @@ impl Context {
|
||||
|
||||
/// Read-only access to [`PassState`].
|
||||
///
|
||||
/// This is only valid during the call to [`Self::run`] (between [`Self::begin_pass`] and [`Self::end_pass`]).
|
||||
/// This is only valid during the call to [`Self::run_ui`] (between [`Self::begin_pass`] and [`Self::end_pass`]).
|
||||
#[inline]
|
||||
pub(crate) fn pass_state<R>(&self, reader: impl FnOnce(&PassState) -> R) -> R {
|
||||
self.write(move |ctx| reader(&ctx.viewport().this_pass))
|
||||
@@ -1057,7 +1013,7 @@ impl Context {
|
||||
|
||||
/// Read-write access to [`PassState`].
|
||||
///
|
||||
/// This is only valid during the call to [`Self::run`] (between [`Self::begin_pass`] and [`Self::end_pass`]).
|
||||
/// This is only valid during the call to [`Self::run_ui`] (between [`Self::begin_pass`] and [`Self::end_pass`]).
|
||||
#[inline]
|
||||
pub(crate) fn pass_state_mut<R>(&self, writer: impl FnOnce(&mut PassState) -> R) -> R {
|
||||
self.write(move |ctx| writer(&mut ctx.viewport().this_pass))
|
||||
@@ -1073,7 +1029,7 @@ impl Context {
|
||||
|
||||
/// Read-only access to [`Fonts`].
|
||||
///
|
||||
/// Not valid until first call to [`Context::run()`].
|
||||
/// Not valid until first call to [`Context::run_ui()`].
|
||||
/// That's because since we don't know the proper `pixels_per_point` until then.
|
||||
#[inline]
|
||||
pub fn fonts<R>(&self, reader: impl FnOnce(&FontsView<'_>) -> R) -> R {
|
||||
@@ -1090,7 +1046,7 @@ impl Context {
|
||||
|
||||
/// Read-write access to [`Fonts`].
|
||||
///
|
||||
/// Not valid until first call to [`Context::run()`].
|
||||
/// Not valid until first call to [`Context::run_ui()`].
|
||||
/// That's because since we don't know the proper `pixels_per_point` until then.
|
||||
#[inline]
|
||||
pub fn fonts_mut<R>(&self, reader: impl FnOnce(&mut FontsView<'_>) -> R) -> R {
|
||||
@@ -1666,7 +1622,7 @@ impl Context {
|
||||
|
||||
/// The total number of completed frames.
|
||||
///
|
||||
/// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
|
||||
/// Starts at zero, and is incremented once at the end of each call to [`Self::run_ui`].
|
||||
///
|
||||
/// This is always smaller or equal to [`Self::cumulative_pass_nr`].
|
||||
pub fn cumulative_frame_nr(&self) -> u64 {
|
||||
@@ -1675,7 +1631,7 @@ impl Context {
|
||||
|
||||
/// The total number of completed frames.
|
||||
///
|
||||
/// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
|
||||
/// Starts at zero, and is incremented once at the end of each call to [`Self::run_ui`].
|
||||
///
|
||||
/// This is always smaller or equal to [`Self::cumulative_pass_nr_for`].
|
||||
pub fn cumulative_frame_nr_for(&self, id: ViewportId) -> u64 {
|
||||
@@ -1695,7 +1651,7 @@ impl Context {
|
||||
|
||||
/// The total number of completed passes (usually there is one pass per rendered frame).
|
||||
///
|
||||
/// Starts at zero, and is incremented for each completed pass inside of [`Self::run`] (usually once).
|
||||
/// Starts at zero, and is incremented for each completed pass inside of [`Self::run_ui`] (usually once).
|
||||
///
|
||||
/// If you instead want to know which pass index this is within the current frame,
|
||||
/// use [`Self::current_pass_index`].
|
||||
@@ -1705,7 +1661,7 @@ impl Context {
|
||||
|
||||
/// The total number of completed passes (usually there is one pass per rendered frame).
|
||||
///
|
||||
/// Starts at zero, and is incremented for each completed pass inside of [`Self::run`] (usually once).
|
||||
/// Starts at zero, and is incremented for each completed pass inside of [`Self::run_ui`] (usually once).
|
||||
pub fn cumulative_pass_nr_for(&self, id: ViewportId) -> u64 {
|
||||
self.read(|ctx| {
|
||||
ctx.viewports
|
||||
@@ -2080,7 +2036,7 @@ impl Context {
|
||||
self.options(|opt| opt.theme())
|
||||
}
|
||||
|
||||
/// The [`Theme`] used to select between dark and light [`Self::style`]
|
||||
/// The [`Theme`] used to select between dark and light [`Self::global_style`]
|
||||
/// as the active style used by all subsequent popups, menus, etc.
|
||||
///
|
||||
/// Example:
|
||||
@@ -2097,12 +2053,6 @@ impl Context {
|
||||
self.options(|opt| Arc::clone(opt.style()))
|
||||
}
|
||||
|
||||
/// The currently active [`Style`] used by all subsequent popups, menus, etc.
|
||||
#[deprecated = "Renamed to `global_style` to avoid confusion with `ui.style()`"]
|
||||
pub fn style(&self) -> Arc<Style> {
|
||||
self.options(|opt| Arc::clone(opt.style()))
|
||||
}
|
||||
|
||||
/// Mutate the currently active [`Style`] used by all subsequent popups, menus, etc.
|
||||
/// Use [`Self::all_styles_mut`] to mutate both dark and light mode styles.
|
||||
///
|
||||
@@ -2117,21 +2067,6 @@ impl Context {
|
||||
self.options_mut(|opt| mutate_style(Arc::make_mut(opt.style_mut())));
|
||||
}
|
||||
|
||||
/// Mutate the currently active [`Style`] used by all subsequent popups, menus, etc.
|
||||
/// Use [`Self::all_styles_mut`] to mutate both dark and light mode styles.
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// # let mut ctx = egui::Context::default();
|
||||
/// ctx.global_style_mut(|style| {
|
||||
/// style.spacing.item_spacing = egui::vec2(10.0, 20.0);
|
||||
/// });
|
||||
/// ```
|
||||
#[deprecated = "Renamed to `global_style_mut` to avoid confusion with `ui.style_mut()`"]
|
||||
pub fn style_mut(&self, mutate_style: impl FnOnce(&mut Style)) {
|
||||
self.options_mut(|opt| mutate_style(Arc::make_mut(opt.style_mut())));
|
||||
}
|
||||
|
||||
/// The currently active [`Style`] used by all new popups, menus, etc.
|
||||
///
|
||||
/// Use [`Self::all_styles_mut`] to mutate both dark and light mode styles.
|
||||
@@ -2143,18 +2078,6 @@ impl Context {
|
||||
self.options_mut(|opt| *opt.style_mut() = style.into());
|
||||
}
|
||||
|
||||
/// The currently active [`Style`] used by all new popups, menus, etc.
|
||||
///
|
||||
/// Use [`Self::all_styles_mut`] to mutate both dark and light mode styles.
|
||||
///
|
||||
/// You can also change this using [`Self::style_mut`].
|
||||
///
|
||||
/// You can use [`Ui::style_mut`] to change the style of a single [`Ui`].
|
||||
#[deprecated = "Renamed to `set_global_style` to avoid confusion with `ui.set_style()`"]
|
||||
pub fn set_style(&self, style: impl Into<Arc<Style>>) {
|
||||
self.options_mut(|opt| *opt.style_mut() = style.into());
|
||||
}
|
||||
|
||||
/// Mutate the [`Style`]s used by all subsequent popups, menus, etc. in both dark and light mode.
|
||||
///
|
||||
/// Example:
|
||||
@@ -2418,13 +2341,6 @@ impl Context {
|
||||
output
|
||||
}
|
||||
|
||||
/// Call at the end of each frame if you called [`Context::begin_pass`].
|
||||
#[must_use]
|
||||
#[deprecated = "Renamed end_pass"]
|
||||
pub fn end_frame(&self) -> FullOutput {
|
||||
self.end_pass()
|
||||
}
|
||||
|
||||
/// Called at the end of the pass.
|
||||
#[cfg(debug_assertions)]
|
||||
fn debug_painting(&self) {
|
||||
@@ -2849,21 +2765,6 @@ impl Context {
|
||||
self.input(|i| i.viewport_rect()).round_ui()
|
||||
}
|
||||
|
||||
/// Position and size of the egui area.
|
||||
#[deprecated(
|
||||
note = "screen_rect has been split into viewport_rect() and content_rect(). You likely should use content_rect()"
|
||||
)]
|
||||
pub fn screen_rect(&self) -> Rect {
|
||||
self.input(|i| i.content_rect()).round_ui()
|
||||
}
|
||||
|
||||
/// How much space is still available after panels have been added.
|
||||
#[deprecated = "Use content_rect (or viewport_rect) instead"]
|
||||
pub fn available_rect(&self) -> Rect {
|
||||
#[expect(deprecated)] // legacy
|
||||
self.pass_state(|s| s.available_rect()).round_ui()
|
||||
}
|
||||
|
||||
/// How much space is used by windows and the top-level [`Ui`].
|
||||
pub fn globally_used_rect(&self) -> Rect {
|
||||
self.write(|ctx| {
|
||||
@@ -2871,10 +2772,7 @@ impl Context {
|
||||
let root_ui_min_rect =
|
||||
(viewport.this_pass.root_ui_min_rect).or(viewport.prev_pass.root_ui_min_rect);
|
||||
|
||||
let mut used = root_ui_min_rect.unwrap_or_else(|| {
|
||||
#[expect(deprecated)] // legacy
|
||||
ctx.viewport().this_pass.used_by_panels
|
||||
});
|
||||
let mut used = root_ui_min_rect.unwrap_or(Rect::NOTHING);
|
||||
for (_id, window) in ctx.memory.areas().visible_windows() {
|
||||
used |= window.rect();
|
||||
}
|
||||
@@ -2882,20 +2780,6 @@ impl Context {
|
||||
})
|
||||
}
|
||||
|
||||
/// How much space is used by windows and the top-level [`Ui`].
|
||||
#[deprecated = "Renamed to globally_used_rect"]
|
||||
pub fn used_rect(&self) -> Rect {
|
||||
self.globally_used_rect()
|
||||
}
|
||||
|
||||
/// How much space is used by windows and the top-level [`Ui`].
|
||||
///
|
||||
/// You can shrink your egui area to this size and still fit all egui components.
|
||||
#[deprecated = "Use globally_used_rect instead"]
|
||||
pub fn used_size(&self) -> Vec2 {
|
||||
(self.globally_used_rect().max - Pos2::ZERO).round_ui()
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/// Is the pointer (mouse/touch) over any egui area?
|
||||
@@ -2916,21 +2800,13 @@ impl Context {
|
||||
// Modern `run_ui` code
|
||||
!root_ui_available_rect.contains(pointer_pos)
|
||||
} else {
|
||||
// Legacy code
|
||||
#[expect(deprecated)]
|
||||
!self.pass_state(|state| state.unused_rect.contains(pointer_pos))
|
||||
true // We shouldn't get here, but who knows
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Is the pointer (mouse/touch) over any egui area?
|
||||
#[deprecated = "Renamed to is_pointer_over_egui"]
|
||||
pub fn is_pointer_over_area(&self) -> bool {
|
||||
self.is_pointer_over_egui()
|
||||
}
|
||||
|
||||
/// True if egui is currently interested in the pointer (mouse or touch).
|
||||
///
|
||||
/// Could be the pointer is hovering over a [`crate::Window`] or the user is dragging a widget.
|
||||
@@ -2942,17 +2818,6 @@ impl Context {
|
||||
|| (self.is_pointer_over_egui() && !self.input(|i| i.pointer.any_down()))
|
||||
}
|
||||
|
||||
/// True if egui is currently interested in the pointer (mouse or touch).
|
||||
///
|
||||
/// Could be the pointer is hovering over a [`crate::Window`] or the user is dragging a widget.
|
||||
/// If `false`, the pointer is outside of any egui area and so
|
||||
/// you may be interested in what it is doing (e.g. controlling your game).
|
||||
/// Returns `false` if a drag started outside of egui and then moved over an egui area.
|
||||
#[deprecated = "Renamed to egui_wants_pointer_input"]
|
||||
pub fn wants_pointer_input(&self) -> bool {
|
||||
self.egui_wants_pointer_input()
|
||||
}
|
||||
|
||||
/// Is egui currently using the pointer position (e.g. dragging a slider)?
|
||||
///
|
||||
/// NOTE: this will return `false` if the pointer is just hovering over an egui area.
|
||||
@@ -2960,25 +2825,11 @@ impl Context {
|
||||
self.memory(|m| m.interaction().is_using_pointer())
|
||||
}
|
||||
|
||||
/// Is egui currently using the pointer position (e.g. dragging a slider)?
|
||||
///
|
||||
/// NOTE: this will return `false` if the pointer is just hovering over an egui area.
|
||||
#[deprecated = "Renamed to egui_is_using_pointer"]
|
||||
pub fn is_using_pointer(&self) -> bool {
|
||||
self.egui_is_using_pointer()
|
||||
}
|
||||
|
||||
/// If `true`, egui is currently listening on text input (e.g. typing text in a [`crate::TextEdit`]).
|
||||
pub fn egui_wants_keyboard_input(&self) -> bool {
|
||||
self.memory(|m| m.focused().is_some())
|
||||
}
|
||||
|
||||
/// If `true`, egui is currently listening on text input (e.g. typing text in a [`crate::TextEdit`]).
|
||||
#[deprecated = "Renamed to egui_wants_keyboard_input"]
|
||||
pub fn wants_keyboard_input(&self) -> bool {
|
||||
self.egui_wants_keyboard_input()
|
||||
}
|
||||
|
||||
/// Is the currently focused widget a text edit?
|
||||
pub fn text_edit_focused(&self) -> bool {
|
||||
if let Some(id) = self.memory(|mem| mem.focused()) {
|
||||
@@ -2998,18 +2849,6 @@ impl Context {
|
||||
self.pass_state_mut(|fs| fs.highlight_next_pass.insert(id));
|
||||
}
|
||||
|
||||
/// Is an egui context menu open?
|
||||
///
|
||||
/// This only works with the old, deprecated [`crate::menu`] API.
|
||||
#[expect(deprecated)]
|
||||
#[deprecated = "Use `any_popup_open` instead"]
|
||||
pub fn is_context_menu_open(&self) -> bool {
|
||||
self.data(|d| {
|
||||
d.get_temp::<crate::menu::BarState>(crate::menu::CONTEXT_MENU_ID_STR.into())
|
||||
.is_some_and(|state| state.has_root())
|
||||
})
|
||||
}
|
||||
|
||||
/// Is a popup or (context) menu open?
|
||||
///
|
||||
/// Will return false for [`crate::Tooltip`]s (which are technically popups as well).
|
||||
@@ -3020,18 +2859,6 @@ impl Context {
|
||||
.any(|layer| !layer.open_popups.is_empty())
|
||||
})
|
||||
}
|
||||
|
||||
/// Is a popup or (context) menu open?
|
||||
///
|
||||
/// Will return false for [`crate::Tooltip`]s (which are technically popups as well).
|
||||
#[deprecated = "Renamed to any_popup_open"]
|
||||
pub fn is_popup_open(&self) -> bool {
|
||||
self.pass_state_mut(|fs| {
|
||||
fs.layers
|
||||
.values()
|
||||
.any(|layer| !layer.open_popups.is_empty())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Ergonomic methods to forward some calls often used in 'if let' without holding the borrow
|
||||
@@ -3646,17 +3473,6 @@ impl Context {
|
||||
}
|
||||
});
|
||||
|
||||
#[expect(deprecated)]
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(format!(
|
||||
"{} menu bars",
|
||||
self.data(|d| d.count::<crate::menu::BarState>())
|
||||
));
|
||||
if ui.button("Reset").clicked() {
|
||||
self.data_mut(|d| d.remove_by_type::<crate::menu::BarState>());
|
||||
}
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(format!(
|
||||
"{} scroll areas",
|
||||
@@ -4009,8 +3825,8 @@ impl Context {
|
||||
/// When called, the integration needs to:
|
||||
/// * Check if there already is a window for this viewport id, and if not open one
|
||||
/// * Set the window attributes (position, size, …) based on [`ImmediateViewport::builder`].
|
||||
/// * Call [`Context::run`] with [`ImmediateViewport::viewport_ui_cb`].
|
||||
/// * Handle the output from [`Context::run`], including rendering
|
||||
/// * Call [`Context::run_ui`] with [`ImmediateViewport::viewport_ui_cb`].
|
||||
/// * Handle the output from [`Context::run_ui`], including rendering
|
||||
pub fn set_immediate_viewport_renderer(
|
||||
callback: impl for<'a> Fn(&Self, ImmediateViewport<'a>) + 'static,
|
||||
) {
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
/// Set the values that make sense, leave the rest at their `Default::default()`.
|
||||
///
|
||||
/// You can check if `egui` is using the inputs using
|
||||
/// [`crate::Context::wants_pointer_input`] and [`crate::Context::wants_keyboard_input`].
|
||||
/// [`crate::Context::egui_wants_pointer_input`] and [`crate::Context::egui_wants_keyboard_input`].
|
||||
///
|
||||
/// All coordinates are in points (logical pixels) with origin (0, 0) in the top left .corner.
|
||||
///
|
||||
@@ -64,8 +64,8 @@ pub struct RawInput {
|
||||
/// In-order events received this frame.
|
||||
///
|
||||
/// There is currently no way to know if egui handles a particular event,
|
||||
/// but you can check if egui is using the keyboard with [`crate::Context::wants_keyboard_input`]
|
||||
/// and/or the pointer (mouse/touch) with [`crate::Context::is_using_pointer`].
|
||||
/// but you can check if egui is using the keyboard with [`crate::Context::egui_wants_keyboard_input`]
|
||||
/// and/or the pointer (mouse/touch) with [`crate::Context::egui_is_using_pointer`].
|
||||
pub events: Vec<Event>,
|
||||
|
||||
/// Dragged files hovering over egui.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::{OrderedViewportIdMap, RepaintCause, ViewportOutput, WidgetType};
|
||||
|
||||
/// What egui emits each frame from [`crate::Context::run`].
|
||||
/// What egui emits each frame from [`crate::Context::run_ui`].
|
||||
///
|
||||
/// The backend should use this.
|
||||
#[derive(Clone, Default)]
|
||||
|
||||
@@ -2,7 +2,7 @@ use ahash::HashMap;
|
||||
|
||||
use emath::TSTransform;
|
||||
|
||||
use crate::{LayerId, Pos2, Sense, WidgetRect, WidgetRects, ahash, emath, id::IdSet};
|
||||
use crate::{LayerId, Pos2, Sense, WidgetRect, WidgetRects, emath, id::IdSet};
|
||||
|
||||
/// Result of a hit-test against [`WidgetRects`].
|
||||
///
|
||||
|
||||
@@ -209,7 +209,7 @@ impl InputOptions {
|
||||
/// You can access this with [`crate::Context::input`].
|
||||
///
|
||||
/// You can check if `egui` is using the inputs using
|
||||
/// [`crate::Context::wants_pointer_input`] and [`crate::Context::wants_keyboard_input`].
|
||||
/// [`crate::Context::egui_wants_pointer_input`] and [`crate::Context::egui_wants_keyboard_input`].
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct InputState {
|
||||
@@ -522,14 +522,6 @@ impl InputState {
|
||||
self.viewport_rect
|
||||
}
|
||||
|
||||
/// Position and size of the egui area.
|
||||
#[deprecated(
|
||||
note = "screen_rect has been split into viewport_rect() and content_rect(). You likely should use content_rect()"
|
||||
)]
|
||||
pub fn screen_rect(&self) -> Rect {
|
||||
self.content_rect()
|
||||
}
|
||||
|
||||
/// Get the safe area insets.
|
||||
///
|
||||
/// This represents the area of the screen covered by status bars, navigation controls, notches,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Handles paint layers, i.e. how things
|
||||
//! are sometimes painted behind or in front of other things.
|
||||
|
||||
use crate::{Id, IdMap, Rect, ahash, epaint};
|
||||
use crate::{Id, IdMap, Rect, epaint};
|
||||
use epaint::{ClippedShape, Shape, emath::TSTransform};
|
||||
|
||||
/// Different layer categories
|
||||
@@ -86,12 +86,6 @@ impl LayerId {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[deprecated = "Use `Memory::allows_interaction` instead"]
|
||||
pub fn allow_interaction(&self) -> bool {
|
||||
self.order.allow_interaction()
|
||||
}
|
||||
|
||||
/// Short and readable summary
|
||||
pub fn short_debug_format(&self) -> String {
|
||||
format!(
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
//! loop {
|
||||
//! let raw_input: egui::RawInput = gather_input();
|
||||
//!
|
||||
//! let full_output = ctx.run(raw_input, |ctx| {
|
||||
//! egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
//! let full_output = ctx.run_ui(raw_input, |ui| {
|
||||
//! egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
//! ui.label("Hello world!");
|
||||
//! if ui.button("Click me").clicked() {
|
||||
//! // take some action here
|
||||
@@ -407,8 +407,6 @@ pub mod layers;
|
||||
mod layout;
|
||||
pub mod load;
|
||||
mod memory;
|
||||
#[deprecated = "Use `egui::containers::menu` instead"]
|
||||
pub mod menu;
|
||||
pub mod os;
|
||||
mod painter;
|
||||
mod pass_state;
|
||||
@@ -434,9 +432,6 @@ mod callstack;
|
||||
|
||||
pub use accesskit;
|
||||
|
||||
#[deprecated = "Use the ahash crate directly."]
|
||||
pub use ahash;
|
||||
|
||||
pub use epaint;
|
||||
pub use epaint::ecolor;
|
||||
pub use epaint::emath;
|
||||
@@ -499,9 +494,6 @@ pub use self::{
|
||||
widgets::*,
|
||||
};
|
||||
|
||||
#[deprecated = "Renamed to CornerRadius"]
|
||||
pub type Rounding = CornerRadius;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Helper function that adds a label when compiling with debug assertions enabled.
|
||||
|
||||
@@ -199,7 +199,7 @@ pub struct Options {
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub light_style: std::sync::Arc<Style>,
|
||||
|
||||
/// Preference for selection between dark and light [`crate::Context::style`]
|
||||
/// Preference for selection between dark and light [`crate::Context::global_style`]
|
||||
/// as the active style used by all subsequent windows, panels, etc.
|
||||
///
|
||||
/// Default: `ThemePreference::System`.
|
||||
@@ -272,7 +272,7 @@ pub struct Options {
|
||||
///
|
||||
/// If this is `1`, [`crate::Context::request_discard`] will be ignored.
|
||||
///
|
||||
/// Multi-pass is supported by [`crate::Context::run`].
|
||||
/// Multi-pass is supported by [`crate::Context::run_ui`].
|
||||
///
|
||||
/// See [`crate::Context::request_discard`] for more.
|
||||
pub max_passes: NonZeroUsize,
|
||||
@@ -820,12 +820,6 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
/// The currently set transform of a layer.
|
||||
#[deprecated = "Use `Context::layer_transform_to_global` instead"]
|
||||
pub fn layer_transforms(&self, layer_id: LayerId) -> Option<TSTransform> {
|
||||
self.to_global.get(&layer_id).copied()
|
||||
}
|
||||
|
||||
/// An iterator over all layers. Back-to-front, top is last.
|
||||
pub fn layer_ids(&self) -> impl ExactSizeIterator<Item = LayerId> + '_ {
|
||||
self.areas().order().iter().copied()
|
||||
@@ -1052,40 +1046,27 @@ impl OpenPopup {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## Deprecated popup API
|
||||
/// Use [`crate::Popup`] instead.
|
||||
/// ## Popup state (internal API)
|
||||
///
|
||||
/// Used by [`crate::Popup`].
|
||||
impl Memory {
|
||||
/// Is the given popup open?
|
||||
#[deprecated = "Use Popup::is_id_open instead"]
|
||||
pub fn is_popup_open(&self, popup_id: Id) -> bool {
|
||||
pub(crate) fn is_popup_open(&self, popup_id: Id) -> bool {
|
||||
self.popups
|
||||
.get(&self.viewport_id)
|
||||
.is_some_and(|state| state.id == popup_id)
|
||||
|| self.everything_is_visible()
|
||||
}
|
||||
|
||||
/// Is any popup open?
|
||||
#[deprecated = "Use Popup::is_any_open instead"]
|
||||
pub fn any_popup_open(&self) -> bool {
|
||||
pub(crate) fn any_popup_open(&self) -> bool {
|
||||
self.popups.contains_key(&self.viewport_id) || self.everything_is_visible()
|
||||
}
|
||||
|
||||
/// Open the given popup and close all others.
|
||||
///
|
||||
/// Note that you must call `keep_popup_open` on subsequent frames as long as the popup is open.
|
||||
#[deprecated = "Use Popup::open_id instead"]
|
||||
pub fn open_popup(&mut self, popup_id: Id) {
|
||||
pub(crate) fn open_popup(&mut self, popup_id: Id) {
|
||||
self.popups
|
||||
.insert(self.viewport_id, OpenPopup::new(popup_id, None));
|
||||
}
|
||||
|
||||
/// Popups must call this every frame while open.
|
||||
///
|
||||
/// This is needed because in some cases popups can go away without `close_popup` being
|
||||
/// called. For example, when a context menu is open and the underlying widget stops
|
||||
/// being rendered.
|
||||
#[deprecated = "Use Popup::show instead"]
|
||||
pub fn keep_popup_open(&mut self, popup_id: Id) {
|
||||
pub(crate) fn keep_popup_open(&mut self, popup_id: Id) {
|
||||
if let Some(state) = self.popups.get_mut(&self.viewport_id)
|
||||
&& state.id == popup_id
|
||||
{
|
||||
@@ -1093,43 +1074,27 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
/// Open the popup and remember its position.
|
||||
#[deprecated = "Use Popup with PopupAnchor::Position instead"]
|
||||
pub fn open_popup_at(&mut self, popup_id: Id, pos: impl Into<Option<Pos2>>) {
|
||||
pub(crate) fn open_popup_at(&mut self, popup_id: Id, pos: impl Into<Option<Pos2>>) {
|
||||
self.popups
|
||||
.insert(self.viewport_id, OpenPopup::new(popup_id, pos.into()));
|
||||
}
|
||||
|
||||
/// Get the position for this popup.
|
||||
#[deprecated = "Use Popup::position_of_id instead"]
|
||||
pub fn popup_position(&self, id: Id) -> Option<Pos2> {
|
||||
pub(crate) fn popup_position(&self, id: Id) -> Option<Pos2> {
|
||||
let state = self.popups.get(&self.viewport_id)?;
|
||||
if state.id == id { state.pos } else { None }
|
||||
}
|
||||
|
||||
/// Close any currently open popup.
|
||||
#[deprecated = "Use Popup::close_all instead"]
|
||||
pub fn close_all_popups(&mut self) {
|
||||
pub(crate) fn close_all_popups(&mut self) {
|
||||
self.popups.clear();
|
||||
}
|
||||
|
||||
/// Close the given popup, if it is open.
|
||||
///
|
||||
/// See also [`Self::close_all_popups`] if you want to close any / all currently open popups.
|
||||
#[deprecated = "Use Popup::close_id instead"]
|
||||
pub fn close_popup(&mut self, popup_id: Id) {
|
||||
#[expect(deprecated)]
|
||||
pub(crate) fn close_popup(&mut self, popup_id: Id) {
|
||||
if self.is_popup_open(popup_id) {
|
||||
self.popups.remove(&self.viewport_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Toggle the given popup between closed and open.
|
||||
///
|
||||
/// Note: At most, only one popup can be open at a time.
|
||||
#[deprecated = "Use Popup::toggle_id instead"]
|
||||
pub fn toggle_popup(&mut self, popup_id: Id) {
|
||||
#[expect(deprecated)]
|
||||
pub(crate) fn toggle_popup(&mut self, popup_id: Id) {
|
||||
if self.is_popup_open(popup_id) {
|
||||
self.close_popup(popup_id);
|
||||
} else {
|
||||
|
||||
@@ -1,781 +0,0 @@
|
||||
#![expect(deprecated)]
|
||||
//! Deprecated menu API - Use [`crate::containers::menu`] instead.
|
||||
//!
|
||||
//! Usage:
|
||||
//! ```
|
||||
//! fn show_menu(ui: &mut egui::Ui) {
|
||||
//! use egui::{menu, Button};
|
||||
//!
|
||||
//! menu::bar(ui, |ui| {
|
||||
//! ui.menu_button("File", |ui| {
|
||||
//! if ui.button("Open").clicked() {
|
||||
//! // …
|
||||
//! }
|
||||
//! });
|
||||
//! });
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use super::{
|
||||
Align, Context, Id, InnerResponse, PointerState, Pos2, Rect, Response, Sense, TextStyle, Ui,
|
||||
Vec2, style::WidgetVisuals,
|
||||
};
|
||||
use crate::{
|
||||
Align2, Area, Color32, Frame, Key, LayerId, Layout, NumExt as _, Order, Stroke, Style,
|
||||
TextWrapMode, UiKind, WidgetText, epaint, vec2,
|
||||
widgets::{Button, ImageButton},
|
||||
};
|
||||
use epaint::mutex::RwLock;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// What is saved between frames.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct BarState {
|
||||
open_menu: MenuRootManager,
|
||||
}
|
||||
|
||||
impl BarState {
|
||||
pub fn load(ctx: &Context, bar_id: Id) -> Self {
|
||||
ctx.data_mut(|d| d.get_temp::<Self>(bar_id).unwrap_or_default())
|
||||
}
|
||||
|
||||
pub fn store(self, ctx: &Context, bar_id: Id) {
|
||||
ctx.data_mut(|d| d.insert_temp(bar_id, self));
|
||||
}
|
||||
|
||||
/// Show a menu at pointer if primary-clicked response.
|
||||
///
|
||||
/// Should be called from [`Context`] on a [`Response`]
|
||||
pub fn bar_menu<R>(
|
||||
&mut self,
|
||||
button: &Response,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<InnerResponse<R>> {
|
||||
MenuRoot::stationary_click_interaction(button, &mut self.open_menu);
|
||||
self.open_menu.show(button, add_contents)
|
||||
}
|
||||
|
||||
pub(crate) fn has_root(&self) -> bool {
|
||||
self.open_menu.inner.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for BarState {
|
||||
type Target = MenuRootManager;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.open_menu
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for BarState {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.open_menu
|
||||
}
|
||||
}
|
||||
|
||||
fn set_menu_style(style: &mut Style) {
|
||||
if style.compact_menu_style {
|
||||
style.spacing.button_padding = vec2(2.0, 0.0);
|
||||
style.visuals.widgets.active.bg_stroke = Stroke::NONE;
|
||||
style.visuals.widgets.hovered.bg_stroke = Stroke::NONE;
|
||||
style.visuals.widgets.inactive.weak_bg_fill = Color32::TRANSPARENT;
|
||||
style.visuals.widgets.inactive.bg_stroke = Stroke::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/// The menu bar goes well in a [`crate::Panel::top`],
|
||||
/// but can also be placed in a [`crate::Window`].
|
||||
/// In the latter case you may want to wrap it in [`Frame`].
|
||||
#[deprecated = "Use `egui::MenuBar::new().ui(` instead"]
|
||||
pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
|
||||
ui.horizontal(|ui| {
|
||||
set_menu_style(ui.style_mut());
|
||||
|
||||
// Take full width and fixed height:
|
||||
let height = ui.spacing().interact_size.y;
|
||||
ui.set_min_size(vec2(ui.available_width(), height));
|
||||
|
||||
add_contents(ui)
|
||||
})
|
||||
}
|
||||
|
||||
/// Construct a top level menu in a menu bar. This would be e.g. "File", "Edit" etc.
|
||||
///
|
||||
/// Responds to primary clicks.
|
||||
///
|
||||
/// Returns `None` if the menu is not open.
|
||||
pub fn menu_button<R>(
|
||||
ui: &mut Ui,
|
||||
title: impl Into<WidgetText>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
stationary_menu_impl(ui, title, Box::new(add_contents))
|
||||
}
|
||||
|
||||
/// Construct a top level menu with a custom button in a menu bar.
|
||||
///
|
||||
/// Responds to primary clicks.
|
||||
///
|
||||
/// Returns `None` if the menu is not open.
|
||||
pub fn menu_custom_button<R>(
|
||||
ui: &mut Ui,
|
||||
button: Button<'_>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
stationary_menu_button_impl(ui, button, Box::new(add_contents))
|
||||
}
|
||||
|
||||
/// Construct a top level menu with an image in a menu bar. This would be e.g. "File", "Edit" etc.
|
||||
///
|
||||
/// Responds to primary clicks.
|
||||
///
|
||||
/// Returns `None` if the menu is not open.
|
||||
#[deprecated = "Use `menu_custom_button` instead"]
|
||||
pub fn menu_image_button<R>(
|
||||
ui: &mut Ui,
|
||||
image_button: ImageButton<'_>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
stationary_menu_button_impl(
|
||||
ui,
|
||||
Button::image(image_button.image),
|
||||
Box::new(add_contents),
|
||||
)
|
||||
}
|
||||
|
||||
/// Construct a nested sub menu in another menu.
|
||||
///
|
||||
/// Opens on hover.
|
||||
///
|
||||
/// Returns `None` if the menu is not open.
|
||||
pub fn submenu_button<R>(
|
||||
ui: &mut Ui,
|
||||
parent_state: Arc<RwLock<MenuState>>,
|
||||
title: impl Into<WidgetText>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
SubMenu::new(parent_state, title).show(ui, add_contents)
|
||||
}
|
||||
|
||||
/// wrapper for the contents of every menu.
|
||||
fn menu_popup<'c, R>(
|
||||
ctx: &Context,
|
||||
parent_layer: LayerId,
|
||||
menu_state_arc: &Arc<RwLock<MenuState>>,
|
||||
menu_id: Id,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R + 'c,
|
||||
) -> InnerResponse<R> {
|
||||
let pos = {
|
||||
let mut menu_state = menu_state_arc.write();
|
||||
menu_state.entry_count = 0;
|
||||
menu_state.rect.min
|
||||
};
|
||||
|
||||
let area_id = menu_id.with("__menu");
|
||||
|
||||
ctx.pass_state_mut(|fs| {
|
||||
fs.layers
|
||||
.entry(parent_layer)
|
||||
.or_default()
|
||||
.open_popups
|
||||
.insert(area_id)
|
||||
});
|
||||
|
||||
let area = Area::new(area_id)
|
||||
.kind(UiKind::Menu)
|
||||
.order(Order::Foreground)
|
||||
.fixed_pos(pos)
|
||||
.default_width(ctx.global_style().spacing.menu_width)
|
||||
.sense(Sense::hover());
|
||||
|
||||
let mut sizing_pass = false;
|
||||
|
||||
let area_response = area.show(ctx, |ui| {
|
||||
sizing_pass = ui.is_sizing_pass();
|
||||
|
||||
set_menu_style(ui.style_mut());
|
||||
|
||||
Frame::menu(ui.style())
|
||||
.show(ui, |ui| {
|
||||
ui.set_menu_state(Some(Arc::clone(menu_state_arc)));
|
||||
ui.with_layout(Layout::top_down_justified(Align::LEFT), add_contents)
|
||||
.inner
|
||||
})
|
||||
.inner
|
||||
});
|
||||
|
||||
let area_rect = area_response.response.rect;
|
||||
|
||||
menu_state_arc.write().rect = if sizing_pass {
|
||||
// During the sizing pass we didn't know the size yet,
|
||||
// so we might have just constrained the position unnecessarily.
|
||||
// Therefore keep the original=desired position until the next frame.
|
||||
Rect::from_min_size(pos, area_rect.size())
|
||||
} else {
|
||||
// We knew the size, and this is where it ended up (potentially constrained to screen).
|
||||
// Remember it for the future:
|
||||
area_rect
|
||||
};
|
||||
|
||||
area_response
|
||||
}
|
||||
|
||||
/// Build a top level menu with a button.
|
||||
///
|
||||
/// Responds to primary clicks.
|
||||
fn stationary_menu_impl<'c, R>(
|
||||
ui: &mut Ui,
|
||||
title: impl Into<WidgetText>,
|
||||
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
let title = title.into();
|
||||
let bar_id = ui.id();
|
||||
let menu_id = bar_id.with(title.text());
|
||||
|
||||
let mut bar_state = BarState::load(ui.ctx(), bar_id);
|
||||
|
||||
let mut button = Button::new(title);
|
||||
|
||||
if bar_state.open_menu.is_menu_open(menu_id) {
|
||||
button = button.fill(ui.visuals().widgets.open.weak_bg_fill);
|
||||
button = button.stroke(ui.visuals().widgets.open.bg_stroke);
|
||||
}
|
||||
|
||||
let button_response = ui.add(button);
|
||||
let inner = bar_state.bar_menu(&button_response, add_contents);
|
||||
|
||||
bar_state.store(ui.ctx(), bar_id);
|
||||
InnerResponse::new(inner.map(|r| r.inner), button_response)
|
||||
}
|
||||
|
||||
/// Build a top level menu with an image button.
|
||||
///
|
||||
/// Responds to primary clicks.
|
||||
fn stationary_menu_button_impl<'c, R>(
|
||||
ui: &mut Ui,
|
||||
button: Button<'_>,
|
||||
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
let bar_id = ui.id();
|
||||
|
||||
let mut bar_state = BarState::load(ui.ctx(), bar_id);
|
||||
let button_response = ui.add(button);
|
||||
let inner = bar_state.bar_menu(&button_response, add_contents);
|
||||
|
||||
bar_state.store(ui.ctx(), bar_id);
|
||||
InnerResponse::new(inner.map(|r| r.inner), button_response)
|
||||
}
|
||||
|
||||
pub(crate) const CONTEXT_MENU_ID_STR: &str = "__egui::context_menu";
|
||||
|
||||
/// Response to secondary clicks (right-clicks) by showing the given menu.
|
||||
pub fn context_menu(
|
||||
response: &Response,
|
||||
add_contents: impl FnOnce(&mut Ui),
|
||||
) -> Option<InnerResponse<()>> {
|
||||
let menu_id = Id::new(CONTEXT_MENU_ID_STR);
|
||||
let mut bar_state = BarState::load(&response.ctx, menu_id);
|
||||
|
||||
MenuRoot::context_click_interaction(response, &mut bar_state);
|
||||
let inner_response = bar_state.show(response, add_contents);
|
||||
|
||||
bar_state.store(&response.ctx, menu_id);
|
||||
inner_response
|
||||
}
|
||||
|
||||
/// Returns `true` if the context menu is opened for this widget.
|
||||
pub fn context_menu_opened(response: &Response) -> bool {
|
||||
let menu_id = Id::new(CONTEXT_MENU_ID_STR);
|
||||
let bar_state = BarState::load(&response.ctx, menu_id);
|
||||
bar_state.is_menu_open(response.id)
|
||||
}
|
||||
|
||||
/// Stores the state for the context menu.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct MenuRootManager {
|
||||
inner: Option<MenuRoot>,
|
||||
}
|
||||
|
||||
impl MenuRootManager {
|
||||
/// Show a menu at pointer if right-clicked response.
|
||||
///
|
||||
/// Should be called from [`Context`] on a [`Response`]
|
||||
pub fn show<R>(
|
||||
&mut self,
|
||||
button: &Response,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<InnerResponse<R>> {
|
||||
if let Some(root) = self.inner.as_mut() {
|
||||
let (menu_response, inner_response) = root.show(button, add_contents);
|
||||
if menu_response.is_close() {
|
||||
self.inner = None;
|
||||
}
|
||||
inner_response
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn is_menu_open(&self, id: Id) -> bool {
|
||||
self.inner.as_ref().map(|m| m.id) == Some(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for MenuRootManager {
|
||||
type Target = Option<MenuRoot>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for MenuRootManager {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
/// Menu root associated with an Id from a Response
|
||||
#[derive(Clone)]
|
||||
pub struct MenuRoot {
|
||||
pub menu_state: Arc<RwLock<MenuState>>,
|
||||
pub id: Id,
|
||||
}
|
||||
|
||||
impl MenuRoot {
|
||||
pub fn new(position: Pos2, id: Id) -> Self {
|
||||
Self {
|
||||
menu_state: Arc::new(RwLock::new(MenuState::new(position))),
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show<R>(
|
||||
&self,
|
||||
button: &Response,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> (MenuResponse, Option<InnerResponse<R>>) {
|
||||
if self.id == button.id {
|
||||
let inner_response = menu_popup(
|
||||
&button.ctx,
|
||||
button.layer_id,
|
||||
&self.menu_state,
|
||||
self.id,
|
||||
add_contents,
|
||||
);
|
||||
let menu_state = self.menu_state.read();
|
||||
|
||||
let escape_pressed = button.ctx.input(|i| i.key_pressed(Key::Escape));
|
||||
if menu_state.response.is_close()
|
||||
|| escape_pressed
|
||||
|| inner_response.response.should_close()
|
||||
{
|
||||
return (MenuResponse::Close, Some(inner_response));
|
||||
}
|
||||
}
|
||||
(MenuResponse::Stay, None)
|
||||
}
|
||||
|
||||
/// Interaction with a stationary menu, i.e. fixed in another Ui.
|
||||
///
|
||||
/// Responds to primary clicks.
|
||||
fn stationary_interaction(button: &Response, root: &mut MenuRootManager) -> MenuResponse {
|
||||
let id = button.id;
|
||||
|
||||
if (button.clicked() && root.is_menu_open(id))
|
||||
|| button.ctx.input(|i| i.key_pressed(Key::Escape))
|
||||
{
|
||||
// menu open and button clicked or esc pressed
|
||||
return MenuResponse::Close;
|
||||
} else if (button.clicked() && !root.is_menu_open(id))
|
||||
|| (button.hovered() && root.is_some())
|
||||
{
|
||||
// menu not open and button clicked
|
||||
// or button hovered while other menu is open
|
||||
let mut pos = button.rect.left_bottom();
|
||||
|
||||
let menu_frame = Frame::menu(&button.ctx.global_style());
|
||||
pos.x -= menu_frame.total_margin().left; // Make fist button in menu align with the parent button
|
||||
pos.y += button.ctx.global_style().spacing.menu_spacing;
|
||||
|
||||
if let Some(root) = root.inner.as_mut() {
|
||||
let menu_rect = root.menu_state.read().rect;
|
||||
let content_rect = button.ctx.input(|i| i.content_rect());
|
||||
|
||||
if pos.y + menu_rect.height() > content_rect.max.y {
|
||||
pos.y = content_rect.max.y - menu_rect.height() - button.rect.height();
|
||||
}
|
||||
|
||||
if pos.x + menu_rect.width() > content_rect.max.x {
|
||||
pos.x = content_rect.max.x - menu_rect.width();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(to_global) = button.ctx.layer_transform_to_global(button.layer_id) {
|
||||
pos = to_global * pos;
|
||||
}
|
||||
|
||||
return MenuResponse::Create(pos, id);
|
||||
} else if button
|
||||
.ctx
|
||||
.input(|i| i.pointer.any_pressed() && i.pointer.primary_down())
|
||||
&& let Some(pos) = button.ctx.input(|i| i.pointer.interact_pos())
|
||||
&& let Some(root) = root.inner.as_mut()
|
||||
&& root.id == id
|
||||
{
|
||||
// pressed somewhere while this menu is open
|
||||
let in_menu = root.menu_state.read().area_contains(pos);
|
||||
if !in_menu {
|
||||
return MenuResponse::Close;
|
||||
}
|
||||
}
|
||||
MenuResponse::Stay
|
||||
}
|
||||
|
||||
/// Interaction with a context menu (secondary click).
|
||||
pub fn context_interaction(response: &Response, root: &mut Option<Self>) -> MenuResponse {
|
||||
let response = response.interact(Sense::click());
|
||||
let hovered = response.hovered();
|
||||
let secondary_clicked = response.secondary_clicked();
|
||||
|
||||
response.ctx.input(|input| {
|
||||
let pointer = &input.pointer;
|
||||
if let Some(pos) = pointer.interact_pos() {
|
||||
let (in_old_menu, destroy) = if let Some(root) = root {
|
||||
let in_old_menu = root.menu_state.read().area_contains(pos);
|
||||
let destroy = !in_old_menu && pointer.any_pressed() && root.id == response.id;
|
||||
(in_old_menu, destroy)
|
||||
} else {
|
||||
(false, false)
|
||||
};
|
||||
if !in_old_menu {
|
||||
if hovered && secondary_clicked {
|
||||
return MenuResponse::Create(pos, response.id);
|
||||
} else if destroy || hovered && pointer.primary_down() {
|
||||
return MenuResponse::Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
MenuResponse::Stay
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_menu_response(root: &mut MenuRootManager, menu_response: MenuResponse) {
|
||||
match menu_response {
|
||||
MenuResponse::Create(pos, id) => {
|
||||
root.inner = Some(Self::new(pos, id));
|
||||
}
|
||||
MenuResponse::Close => root.inner = None,
|
||||
MenuResponse::Stay => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Respond to secondary (right) clicks.
|
||||
pub fn context_click_interaction(response: &Response, root: &mut MenuRootManager) {
|
||||
let menu_response = Self::context_interaction(response, root);
|
||||
Self::handle_menu_response(root, menu_response);
|
||||
}
|
||||
|
||||
// Responds to primary clicks.
|
||||
pub fn stationary_click_interaction(button: &Response, root: &mut MenuRootManager) {
|
||||
let menu_response = Self::stationary_interaction(button, root);
|
||||
Self::handle_menu_response(root, menu_response);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum MenuResponse {
|
||||
Close,
|
||||
Stay,
|
||||
Create(Pos2, Id),
|
||||
}
|
||||
|
||||
impl MenuResponse {
|
||||
pub fn is_close(&self) -> bool {
|
||||
*self == Self::Close
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SubMenuButton {
|
||||
text: WidgetText,
|
||||
icon: WidgetText,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl SubMenuButton {
|
||||
/// The `icon` can be an emoji (e.g. `⏵` right arrow), shown right of the label
|
||||
fn new(text: impl Into<WidgetText>, icon: impl Into<WidgetText>, index: usize) -> Self {
|
||||
Self {
|
||||
text: text.into(),
|
||||
icon: icon.into(),
|
||||
index,
|
||||
}
|
||||
}
|
||||
|
||||
fn visuals<'a>(
|
||||
ui: &'a Ui,
|
||||
response: &Response,
|
||||
menu_state: &MenuState,
|
||||
sub_id: Id,
|
||||
) -> &'a WidgetVisuals {
|
||||
if menu_state.is_open(sub_id) && !response.hovered() {
|
||||
&ui.style().visuals.widgets.open
|
||||
} else {
|
||||
ui.style().interact(response)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn icon(mut self, icon: impl Into<WidgetText>) -> Self {
|
||||
self.icon = icon.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn show(self, ui: &mut Ui, menu_state: &MenuState, sub_id: Id) -> Response {
|
||||
let Self { text, icon, .. } = self;
|
||||
|
||||
let text_style = TextStyle::Button;
|
||||
let sense = Sense::click();
|
||||
|
||||
let text_icon_gap = ui.spacing().item_spacing.x;
|
||||
let button_padding = ui.spacing().button_padding;
|
||||
let total_extra = button_padding + button_padding;
|
||||
let text_available_width = ui.available_width() - total_extra.x;
|
||||
let text_galley = text.into_galley(
|
||||
ui,
|
||||
Some(TextWrapMode::Wrap),
|
||||
text_available_width,
|
||||
text_style.clone(),
|
||||
);
|
||||
|
||||
let icon_available_width = text_available_width - text_galley.size().x;
|
||||
let icon_galley = icon.into_galley(
|
||||
ui,
|
||||
Some(TextWrapMode::Wrap),
|
||||
icon_available_width,
|
||||
text_style,
|
||||
);
|
||||
let text_and_icon_size = Vec2::new(
|
||||
text_galley.size().x + text_icon_gap + icon_galley.size().x,
|
||||
text_galley.size().y.max(icon_galley.size().y),
|
||||
);
|
||||
let mut desired_size = text_and_icon_size + 2.0 * button_padding;
|
||||
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
|
||||
|
||||
let (rect, response) = ui.allocate_at_least(desired_size, sense);
|
||||
response.widget_info(|| {
|
||||
crate::WidgetInfo::labeled(
|
||||
crate::WidgetType::Button,
|
||||
ui.is_enabled(),
|
||||
text_galley.text(),
|
||||
)
|
||||
});
|
||||
|
||||
if ui.is_rect_visible(rect) {
|
||||
let visuals = Self::visuals(ui, &response, menu_state, sub_id);
|
||||
let text_pos = Align2::LEFT_CENTER
|
||||
.align_size_within_rect(text_galley.size(), rect.shrink2(button_padding))
|
||||
.min;
|
||||
let icon_pos = Align2::RIGHT_CENTER
|
||||
.align_size_within_rect(icon_galley.size(), rect.shrink2(button_padding))
|
||||
.min;
|
||||
|
||||
if ui.visuals().button_frame {
|
||||
ui.painter().rect_filled(
|
||||
rect.expand(visuals.expansion),
|
||||
visuals.corner_radius,
|
||||
visuals.weak_bg_fill,
|
||||
);
|
||||
}
|
||||
|
||||
let text_color = visuals.text_color();
|
||||
ui.painter().galley(text_pos, text_galley, text_color);
|
||||
ui.painter().galley(icon_pos, icon_galley, text_color);
|
||||
}
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SubMenu {
|
||||
button: SubMenuButton,
|
||||
parent_state: Arc<RwLock<MenuState>>,
|
||||
}
|
||||
|
||||
impl SubMenu {
|
||||
fn new(parent_state: Arc<RwLock<MenuState>>, text: impl Into<WidgetText>) -> Self {
|
||||
let index = parent_state.write().next_entry_index();
|
||||
Self {
|
||||
button: SubMenuButton::new(text, "⏵", index),
|
||||
parent_state,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show<R>(
|
||||
self,
|
||||
ui: &mut Ui,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
let sub_id = ui.id().with(self.button.index);
|
||||
let response = self.button.show(ui, &self.parent_state.read(), sub_id);
|
||||
self.parent_state
|
||||
.write()
|
||||
.submenu_button_interaction(ui, sub_id, &response);
|
||||
let inner =
|
||||
self.parent_state
|
||||
.write()
|
||||
.show_submenu(ui.ctx(), ui.layer_id(), sub_id, add_contents);
|
||||
InnerResponse::new(inner, response)
|
||||
}
|
||||
}
|
||||
|
||||
/// Components of menu state, public for advanced usage.
|
||||
///
|
||||
/// Usually you don't need to use it directly.
|
||||
pub struct MenuState {
|
||||
/// The opened sub-menu and its [`Id`]
|
||||
sub_menu: Option<(Id, Arc<RwLock<Self>>)>,
|
||||
|
||||
/// Bounding box of this menu (without the sub-menu),
|
||||
/// including the frame and everything.
|
||||
pub rect: Rect,
|
||||
|
||||
/// Used to check if any menu in the tree wants to close
|
||||
pub response: MenuResponse,
|
||||
|
||||
/// Used to hash different [`Id`]s for sub-menus
|
||||
entry_count: usize,
|
||||
}
|
||||
|
||||
impl MenuState {
|
||||
pub fn new(position: Pos2) -> Self {
|
||||
Self {
|
||||
rect: Rect::from_min_size(position, Vec2::ZERO),
|
||||
sub_menu: None,
|
||||
response: MenuResponse::Stay,
|
||||
entry_count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Close menu hierarchy.
|
||||
pub fn close(&mut self) {
|
||||
self.response = MenuResponse::Close;
|
||||
}
|
||||
|
||||
fn show_submenu<R>(
|
||||
&mut self,
|
||||
ctx: &Context,
|
||||
parent_layer: LayerId,
|
||||
id: Id,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
let (sub_response, response) = self.submenu(id).map(|sub| {
|
||||
let inner_response = menu_popup(ctx, parent_layer, sub, id, add_contents);
|
||||
if inner_response.response.should_close() {
|
||||
sub.write().close();
|
||||
}
|
||||
(sub.read().response, inner_response.inner)
|
||||
})?;
|
||||
self.cascade_close_response(sub_response);
|
||||
Some(response)
|
||||
}
|
||||
|
||||
/// Check if position is in the menu hierarchy's area.
|
||||
pub fn area_contains(&self, pos: Pos2) -> bool {
|
||||
self.rect.contains(pos)
|
||||
|| self
|
||||
.sub_menu
|
||||
.as_ref()
|
||||
.is_some_and(|(_, sub)| sub.read().area_contains(pos))
|
||||
}
|
||||
|
||||
fn next_entry_index(&mut self) -> usize {
|
||||
self.entry_count += 1;
|
||||
self.entry_count - 1
|
||||
}
|
||||
|
||||
/// Sense button interaction opening and closing submenu.
|
||||
fn submenu_button_interaction(&mut self, ui: &Ui, sub_id: Id, button: &Response) {
|
||||
let pointer = ui.input(|i| i.pointer.clone());
|
||||
let open = self.is_open(sub_id);
|
||||
if self.moving_towards_current_submenu(&pointer) {
|
||||
// We don't close the submenu if the pointer is on its way to hover it.
|
||||
// ensure to repaint once even when pointer is not moving
|
||||
ui.request_repaint();
|
||||
} else if !open && button.hovered() {
|
||||
// TODO(emilk): open menu to the left if there isn't enough space to the right
|
||||
let mut pos = button.rect.right_top();
|
||||
pos.x = self.rect.right() + ui.spacing().menu_spacing;
|
||||
pos.y -= Frame::menu(ui.style()).total_margin().top; // align the first button in the submenu with the parent button
|
||||
|
||||
self.open_submenu(sub_id, pos);
|
||||
} else if open
|
||||
&& ui.response().contains_pointer()
|
||||
&& !button.hovered()
|
||||
&& !self.hovering_current_submenu(&pointer)
|
||||
{
|
||||
// We are hovering something else in the menu, so close the submenu.
|
||||
self.close_submenu();
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if pointer is moving towards current submenu.
|
||||
fn moving_towards_current_submenu(&self, pointer: &PointerState) -> bool {
|
||||
if pointer.is_still() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(sub_menu) = self.current_submenu()
|
||||
&& let Some(pos) = pointer.hover_pos()
|
||||
{
|
||||
let rect = sub_menu.read().rect;
|
||||
return rect.intersects_ray(pos, pointer.direction().normalized());
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Check if pointer is hovering current submenu.
|
||||
fn hovering_current_submenu(&self, pointer: &PointerState) -> bool {
|
||||
if let Some(sub_menu) = self.current_submenu()
|
||||
&& let Some(pos) = pointer.hover_pos()
|
||||
{
|
||||
return sub_menu.read().area_contains(pos);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Cascade close response to menu root.
|
||||
fn cascade_close_response(&mut self, response: MenuResponse) {
|
||||
if response.is_close() {
|
||||
self.response = response;
|
||||
}
|
||||
}
|
||||
|
||||
fn is_open(&self, id: Id) -> bool {
|
||||
self.sub_id() == Some(id)
|
||||
}
|
||||
|
||||
fn sub_id(&self) -> Option<Id> {
|
||||
self.sub_menu.as_ref().map(|(id, _)| *id)
|
||||
}
|
||||
|
||||
fn current_submenu(&self) -> Option<&Arc<RwLock<Self>>> {
|
||||
self.sub_menu.as_ref().map(|(_, sub)| sub)
|
||||
}
|
||||
|
||||
fn submenu(&self, id: Id) -> Option<&Arc<RwLock<Self>>> {
|
||||
let (k, sub) = self.sub_menu.as_ref()?;
|
||||
if id == *k { Some(sub) } else { None }
|
||||
}
|
||||
|
||||
/// Open submenu at position, if not already open.
|
||||
fn open_submenu(&mut self, id: Id, pos: Pos2) {
|
||||
if !self.is_open(id) {
|
||||
self.sub_menu = Some((id, Arc::new(RwLock::new(Self::new(pos)))));
|
||||
}
|
||||
}
|
||||
|
||||
fn close_submenu(&mut self) {
|
||||
self.sub_menu = None;
|
||||
}
|
||||
}
|
||||
@@ -82,12 +82,6 @@ impl Painter {
|
||||
self.layer_id = layer_id;
|
||||
}
|
||||
|
||||
/// If set, colors will be modified to look like this
|
||||
#[deprecated = "Use `multiply_opacity` instead"]
|
||||
pub fn set_fade_to_color(&mut self, fade_to_color: Option<Color32>) {
|
||||
self.fade_to_color = fade_to_color;
|
||||
}
|
||||
|
||||
/// Set the opacity (alpha multiplier) of everything painted by this painter from this point forward.
|
||||
///
|
||||
/// `opacity` must be between 0.0 and 1.0, where 0.0 means fully transparent (i.e., invisible)
|
||||
@@ -195,41 +189,6 @@ impl Painter {
|
||||
pub fn round_to_pixel_center(&self, point: f32) -> f32 {
|
||||
point.round_to_pixel_center(self.pixels_per_point())
|
||||
}
|
||||
|
||||
/// Useful for pixel-perfect rendering of lines that are one pixel wide (or any odd number of pixels).
|
||||
#[deprecated = "Use `emath::GuiRounding` with `painter.pixels_per_point()` instead"]
|
||||
#[inline]
|
||||
pub fn round_pos_to_pixel_center(&self, pos: Pos2) -> Pos2 {
|
||||
pos.round_to_pixel_center(self.pixels_per_point())
|
||||
}
|
||||
|
||||
/// Useful for pixel-perfect rendering of filled shapes.
|
||||
#[deprecated = "Use `emath::GuiRounding` with `painter.pixels_per_point()` instead"]
|
||||
#[inline]
|
||||
pub fn round_to_pixel(&self, point: f32) -> f32 {
|
||||
point.round_to_pixels(self.pixels_per_point())
|
||||
}
|
||||
|
||||
/// Useful for pixel-perfect rendering.
|
||||
#[deprecated = "Use `emath::GuiRounding` with `painter.pixels_per_point()` instead"]
|
||||
#[inline]
|
||||
pub fn round_vec_to_pixels(&self, vec: Vec2) -> Vec2 {
|
||||
vec.round_to_pixels(self.pixels_per_point())
|
||||
}
|
||||
|
||||
/// Useful for pixel-perfect rendering.
|
||||
#[deprecated = "Use `emath::GuiRounding` with `painter.pixels_per_point()` instead"]
|
||||
#[inline]
|
||||
pub fn round_pos_to_pixels(&self, pos: Pos2) -> Pos2 {
|
||||
pos.round_to_pixels(self.pixels_per_point())
|
||||
}
|
||||
|
||||
/// Useful for pixel-perfect rendering.
|
||||
#[deprecated = "Use `emath::GuiRounding` with `painter.pixels_per_point()` instead"]
|
||||
#[inline]
|
||||
pub fn round_rect_to_pixels(&self, rect: Rect) -> Rect {
|
||||
rect.round_to_pixels(self.pixels_per_point())
|
||||
}
|
||||
}
|
||||
|
||||
/// ## Low level
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#![expect(deprecated)] // TODO(emilk): Remove legacy panels
|
||||
|
||||
use ahash::HashMap;
|
||||
|
||||
use crate::{Align, Id, IdMap, LayerId, Rangef, Rect, Vec2, WidgetRects, id::IdSet, style};
|
||||
@@ -211,20 +209,6 @@ pub struct PassState {
|
||||
/// Only set if [`crate::Context::run_ui`] has been called.
|
||||
pub root_ui_min_rect: Option<Rect>,
|
||||
|
||||
/// Starts off as the `screen_rect`, shrinks as panels are added.
|
||||
/// The [`crate::CentralPanel`] does not change this.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub available_rect: Rect,
|
||||
|
||||
/// Starts off as the `screen_rect`, shrinks as panels are added.
|
||||
/// The [`crate::CentralPanel`] retracts from this.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub unused_rect: Rect,
|
||||
|
||||
/// How much space is used by panels.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub used_by_panels: Rect,
|
||||
|
||||
/// The current scroll area should scroll to this range (horizontal, vertical).
|
||||
pub scroll_target: [Option<ScrollTarget>; 2],
|
||||
|
||||
@@ -257,9 +241,6 @@ impl Default for PassState {
|
||||
tooltips: Default::default(),
|
||||
root_ui_available_rect: None,
|
||||
root_ui_min_rect: None,
|
||||
available_rect: Rect::NAN,
|
||||
unused_rect: Rect::NAN,
|
||||
used_by_panels: Rect::NAN,
|
||||
scroll_target: [None, None],
|
||||
scroll_delta: (Vec2::default(), style::ScrollAnimation::none()),
|
||||
accesskit_state: None,
|
||||
@@ -272,7 +253,7 @@ impl Default for PassState {
|
||||
}
|
||||
|
||||
impl PassState {
|
||||
pub(crate) fn begin_pass(&mut self, content_rect: Rect) {
|
||||
pub(crate) fn begin_pass(&mut self) {
|
||||
profiling::function_scope!();
|
||||
let Self {
|
||||
used_ids,
|
||||
@@ -281,9 +262,6 @@ impl PassState {
|
||||
layers,
|
||||
root_ui_available_rect,
|
||||
root_ui_min_rect,
|
||||
available_rect,
|
||||
unused_rect,
|
||||
used_by_panels,
|
||||
scroll_target,
|
||||
scroll_delta,
|
||||
accesskit_state,
|
||||
@@ -299,9 +277,6 @@ impl PassState {
|
||||
layers.clear();
|
||||
*root_ui_available_rect = None;
|
||||
*root_ui_min_rect = None;
|
||||
*available_rect = content_rect;
|
||||
*unused_rect = content_rect;
|
||||
*used_by_panels = Rect::NOTHING;
|
||||
*scroll_target = [None, None];
|
||||
*scroll_delta = Default::default();
|
||||
|
||||
@@ -314,70 +289,4 @@ impl PassState {
|
||||
|
||||
highlight_next_pass.clear();
|
||||
}
|
||||
|
||||
/// How much space is still available after panels has been added.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub(crate) fn available_rect(&self) -> Rect {
|
||||
debug_assert!(
|
||||
self.available_rect.is_finite(),
|
||||
"Called `available_rect()` before `Context::run()`"
|
||||
);
|
||||
self.available_rect
|
||||
}
|
||||
|
||||
/// Shrink `available_rect`.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub(crate) fn allocate_left_panel(&mut self, panel_rect: Rect) {
|
||||
debug_assert!(
|
||||
panel_rect.min.distance(self.available_rect.min) < 0.1,
|
||||
"Mismatching left panel. You must not create a panel from within another panel."
|
||||
);
|
||||
self.available_rect.min.x = panel_rect.max.x;
|
||||
self.unused_rect.min.x = panel_rect.max.x;
|
||||
self.used_by_panels |= panel_rect;
|
||||
}
|
||||
|
||||
/// Shrink `available_rect`.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub(crate) fn allocate_right_panel(&mut self, panel_rect: Rect) {
|
||||
debug_assert!(
|
||||
panel_rect.max.distance(self.available_rect.max) < 0.1,
|
||||
"Mismatching right panel. You must not create a panel from within another panel."
|
||||
);
|
||||
self.available_rect.max.x = panel_rect.min.x;
|
||||
self.unused_rect.max.x = panel_rect.min.x;
|
||||
self.used_by_panels |= panel_rect;
|
||||
}
|
||||
|
||||
/// Shrink `available_rect`.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub(crate) fn allocate_top_panel(&mut self, panel_rect: Rect) {
|
||||
debug_assert!(
|
||||
panel_rect.min.distance(self.available_rect.min) < 0.1,
|
||||
"Mismatching top panel. You must not create a panel from within another panel."
|
||||
);
|
||||
self.available_rect.min.y = panel_rect.max.y;
|
||||
self.unused_rect.min.y = panel_rect.max.y;
|
||||
self.used_by_panels |= panel_rect;
|
||||
}
|
||||
|
||||
/// Shrink `available_rect`.
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub(crate) fn allocate_bottom_panel(&mut self, panel_rect: Rect) {
|
||||
debug_assert!(
|
||||
panel_rect.max.distance(self.available_rect.max) < 0.1,
|
||||
"Mismatching bottom panel. You must not create a panel from within another panel."
|
||||
);
|
||||
self.available_rect.max.y = panel_rect.min.y;
|
||||
self.unused_rect.max.y = panel_rect.min.y;
|
||||
self.used_by_panels |= panel_rect;
|
||||
}
|
||||
|
||||
#[deprecated = "Only used by legacy Context-Panels"]
|
||||
pub(crate) fn allocate_central_panel(&mut self, panel_rect: Rect) {
|
||||
// Note: we do not shrink `available_rect`, because
|
||||
// we allow windows to cover the CentralPanel.
|
||||
self.unused_rect = Rect::NOTHING; // Nothing left unused after this
|
||||
self.used_by_panels |= panel_rect;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,17 +297,6 @@ pub struct Style {
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub number_formatter: NumberFormatter,
|
||||
|
||||
/// If set, labels, buttons, etc. will use this to determine whether to wrap the text at the
|
||||
/// right edge of the [`Ui`] they are in. By default, this is `None`.
|
||||
///
|
||||
/// **Note**: this API is deprecated, use `wrap_mode` instead.
|
||||
///
|
||||
/// * `None`: use `wrap_mode` instead
|
||||
/// * `Some(true)`: wrap mode defaults to [`crate::TextWrapMode::Wrap`]
|
||||
/// * `Some(false)`: wrap mode defaults to [`crate::TextWrapMode::Extend`]
|
||||
#[deprecated = "Use wrap_mode instead"]
|
||||
pub wrap: Option<bool>,
|
||||
|
||||
/// If set, labels, buttons, etc. will use this to determine whether to wrap or truncate the
|
||||
/// text at the right edge of the [`Ui`] they are in, or to extend it. By default, this is
|
||||
/// `None`.
|
||||
@@ -1166,13 +1155,6 @@ impl Visuals {
|
||||
self.window_stroke
|
||||
}
|
||||
|
||||
/// When fading out things, we fade the colors towards this.
|
||||
#[inline(always)]
|
||||
#[deprecated = "Use disabled_alpha(). Fading is now handled by modifying the alpha channel."]
|
||||
pub fn fade_out_to_color(&self) -> Color32 {
|
||||
self.widgets.noninteractive.weak_bg_fill
|
||||
}
|
||||
|
||||
/// Disabled widgets have their alpha modified by this.
|
||||
#[inline(always)]
|
||||
pub fn disabled_alpha(&self) -> f32 {
|
||||
@@ -1303,11 +1285,6 @@ impl WidgetVisuals {
|
||||
pub fn text_color(&self) -> Color32 {
|
||||
self.fg_stroke.color
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed to corner_radius"]
|
||||
pub fn rounding(&self) -> CornerRadius {
|
||||
self.corner_radius
|
||||
}
|
||||
}
|
||||
|
||||
/// Options for help debug egui by adding extra visualization
|
||||
@@ -1410,7 +1387,6 @@ pub fn default_text_styles() -> BTreeMap<TextStyle, FontId> {
|
||||
|
||||
impl Default for Style {
|
||||
fn default() -> Self {
|
||||
#[expect(deprecated)]
|
||||
Self {
|
||||
override_font_id: None,
|
||||
override_text_style: None,
|
||||
@@ -1418,7 +1394,6 @@ impl Default for Style {
|
||||
text_styles: default_text_styles(),
|
||||
drag_value_text_style: TextStyle::Button,
|
||||
number_formatter: NumberFormatter(Arc::new(emath::format_with_decimals_in_range)),
|
||||
wrap: None,
|
||||
wrap_mode: None,
|
||||
spacing: Spacing::default(),
|
||||
interaction: Interaction::default(),
|
||||
@@ -1724,7 +1699,6 @@ use crate::{
|
||||
|
||||
impl Style {
|
||||
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
||||
#[expect(deprecated)]
|
||||
let Self {
|
||||
override_font_id,
|
||||
override_text_style,
|
||||
@@ -1732,7 +1706,6 @@ impl Style {
|
||||
text_styles,
|
||||
drag_value_text_style,
|
||||
number_formatter: _, // can't change callbacks in the UI
|
||||
wrap: _,
|
||||
wrap_mode,
|
||||
spacing,
|
||||
interaction,
|
||||
|
||||
@@ -97,12 +97,6 @@ impl CCursorRange {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[deprecated = "Use `self.sorted_cursors` instead."]
|
||||
pub fn sorted(&self) -> [CCursor; 2] {
|
||||
self.sorted_cursors()
|
||||
}
|
||||
|
||||
pub fn slice_str<'s>(&self, text: &'s str) -> &'s str {
|
||||
let [min, max] = self.sorted_cursors();
|
||||
slice_char_range(text, min.index..max.index)
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
|
||||
use std::{any::Any, hash::Hash, ops::Deref, sync::Arc};
|
||||
|
||||
use emath::GuiRounding as _;
|
||||
use epaint::mutex::RwLock;
|
||||
|
||||
use crate::containers::menu;
|
||||
use crate::{containers::*, ecolor::*, layout::*, placer::Placer, widgets::*, *};
|
||||
use emath::GuiRounding as _;
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// This is what you use to place widgets.
|
||||
@@ -75,10 +73,6 @@ pub struct Ui {
|
||||
/// where we size up the contents of the Ui, without actually showing it.
|
||||
sizing_pass: bool,
|
||||
|
||||
/// Indicates whether this Ui belongs to a Menu.
|
||||
#[expect(deprecated)]
|
||||
menu_state: Option<Arc<RwLock<crate::menu::MenuState>>>,
|
||||
|
||||
/// The [`UiStack`] for this [`Ui`].
|
||||
stack: Arc<UiStack>,
|
||||
|
||||
@@ -157,7 +151,6 @@ impl Ui {
|
||||
placer,
|
||||
enabled: true,
|
||||
sizing_pass,
|
||||
menu_state: None,
|
||||
stack: Arc::new(ui_stack),
|
||||
sense,
|
||||
min_rect_already_remembered: false,
|
||||
@@ -198,47 +191,6 @@ impl Ui {
|
||||
ui
|
||||
}
|
||||
|
||||
/// Create a new [`Ui`] at a specific region.
|
||||
///
|
||||
/// Note: calling this function twice from the same [`Ui`] will create a conflict of id. Use
|
||||
/// [`Self::scope`] if needed.
|
||||
///
|
||||
/// When in doubt, use `None` for the `UiStackInfo` argument.
|
||||
#[deprecated = "Use ui.new_child() instead"]
|
||||
pub fn child_ui(
|
||||
&mut self,
|
||||
max_rect: Rect,
|
||||
layout: Layout,
|
||||
ui_stack_info: Option<UiStackInfo>,
|
||||
) -> Self {
|
||||
self.new_child(
|
||||
UiBuilder::new()
|
||||
.max_rect(max_rect)
|
||||
.layout(layout)
|
||||
.ui_stack_info(ui_stack_info.unwrap_or_default()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new [`Ui`] at a specific region with a specific id.
|
||||
///
|
||||
/// When in doubt, use `None` for the `UiStackInfo` argument.
|
||||
#[deprecated = "Use ui.new_child() instead"]
|
||||
pub fn child_ui_with_id_source(
|
||||
&mut self,
|
||||
max_rect: Rect,
|
||||
layout: Layout,
|
||||
id_salt: impl Hash,
|
||||
ui_stack_info: Option<UiStackInfo>,
|
||||
) -> Self {
|
||||
self.new_child(
|
||||
UiBuilder::new()
|
||||
.id_salt(id_salt)
|
||||
.max_rect(max_rect)
|
||||
.layout(layout)
|
||||
.ui_stack_info(ui_stack_info.unwrap_or_default()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a child `Ui` with the properties of the given builder.
|
||||
///
|
||||
/// This is a very low-level function.
|
||||
@@ -320,7 +272,6 @@ impl Ui {
|
||||
placer,
|
||||
enabled,
|
||||
sizing_pass,
|
||||
menu_state: self.menu_state.clone(),
|
||||
stack: Arc::new(ui_stack),
|
||||
sense,
|
||||
min_rect_already_remembered: false,
|
||||
@@ -362,18 +313,6 @@ impl Ui {
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
/// Set to true in special cases where we do one frame
|
||||
/// where we size up the contents of the Ui, without actually showing it.
|
||||
///
|
||||
/// This will also turn the Ui invisible.
|
||||
/// Should be called right after [`Self::new`], if at all.
|
||||
#[inline]
|
||||
#[deprecated = "Use UiBuilder.sizing_pass().invisible()"]
|
||||
pub fn set_sizing_pass(&mut self) {
|
||||
self.sizing_pass = true;
|
||||
self.set_invisible();
|
||||
}
|
||||
|
||||
/// Set to true in special cases where we do one frame
|
||||
/// where we size up the contents of the Ui, without actually showing it.
|
||||
#[inline]
|
||||
@@ -412,7 +351,7 @@ impl Ui {
|
||||
|
||||
/// Style options for this [`Ui`] and its children.
|
||||
///
|
||||
/// Note that this may be a different [`Style`] than that of [`Context::style`].
|
||||
/// Note that this may be a different [`Style`] than that of [`Context::global_style`].
|
||||
#[inline]
|
||||
pub fn style(&self) -> &Arc<Style> {
|
||||
&self.style
|
||||
@@ -554,33 +493,6 @@ impl Ui {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calling `set_enabled(false)` will cause the [`Ui`] to deny all future interaction
|
||||
/// and all the widgets will draw with a gray look.
|
||||
///
|
||||
/// Usually it is more convenient to use [`Self::add_enabled_ui`] or [`Self::add_enabled`].
|
||||
///
|
||||
/// Calling `set_enabled(true)` has no effect - it will NOT re-enable the [`Ui`] once disabled.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// # let mut enabled = true;
|
||||
/// ui.group(|ui| {
|
||||
/// ui.checkbox(&mut enabled, "Enable subsection");
|
||||
/// ui.set_enabled(enabled);
|
||||
/// if ui.button("Button that is not always clickable").clicked() {
|
||||
/// /* … */
|
||||
/// }
|
||||
/// });
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use disable(), add_enabled_ui(), or add_enabled() instead"]
|
||||
pub fn set_enabled(&mut self, enabled: bool) {
|
||||
if !enabled {
|
||||
self.disable();
|
||||
}
|
||||
}
|
||||
|
||||
/// If `false`, any widgets added to the [`Ui`] will be invisible and non-interactive.
|
||||
///
|
||||
/// This is `false` if any parent had [`UiBuilder::invisible`]
|
||||
@@ -597,7 +509,7 @@ impl Ui {
|
||||
///
|
||||
/// Once invisible, there is no way to make the [`Ui`] visible again.
|
||||
///
|
||||
/// Usually it is more convenient to use [`Self::add_visible_ui`] or [`Self::add_visible`].
|
||||
/// Usually it is more convenient to use [`Self::add_visible`].
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
@@ -619,34 +531,6 @@ impl Ui {
|
||||
self.disable();
|
||||
}
|
||||
|
||||
/// Calling `set_visible(false)` will cause all further widgets to be invisible,
|
||||
/// yet still allocate space.
|
||||
///
|
||||
/// The widgets will not be interactive (`set_visible(false)` implies `set_enabled(false)`).
|
||||
///
|
||||
/// Calling `set_visible(true)` has no effect.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// # let mut visible = true;
|
||||
/// ui.group(|ui| {
|
||||
/// ui.checkbox(&mut visible, "Show subsection");
|
||||
/// ui.set_visible(visible);
|
||||
/// if ui.button("Button that is not always shown").clicked() {
|
||||
/// /* … */
|
||||
/// }
|
||||
/// });
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use set_invisible(), add_visible_ui(), or add_visible() instead"]
|
||||
pub fn set_visible(&mut self, visible: bool) {
|
||||
if !visible {
|
||||
self.painter.set_invisible();
|
||||
self.disable();
|
||||
}
|
||||
}
|
||||
|
||||
/// Make the widget in this [`Ui`] semi-transparent.
|
||||
///
|
||||
/// `opacity` must be between 0.0 and 1.0, where 0.0 means fully transparent (i.e., invisible)
|
||||
@@ -694,17 +578,8 @@ impl Ui {
|
||||
///
|
||||
/// This is determined first by [`Style::wrap_mode`], and then by the layout of this [`Ui`].
|
||||
pub fn wrap_mode(&self) -> TextWrapMode {
|
||||
#[expect(deprecated)]
|
||||
if let Some(wrap_mode) = self.style.wrap_mode {
|
||||
wrap_mode
|
||||
}
|
||||
// `wrap` handling for backward compatibility
|
||||
else if let Some(wrap) = self.style.wrap {
|
||||
if wrap {
|
||||
TextWrapMode::Wrap
|
||||
} else {
|
||||
TextWrapMode::Extend
|
||||
}
|
||||
} else if let Some(grid) = self.placer.grid() {
|
||||
if grid.wrap_text() {
|
||||
TextWrapMode::Wrap
|
||||
@@ -721,14 +596,6 @@ impl Ui {
|
||||
}
|
||||
}
|
||||
|
||||
/// Should text wrap in this [`Ui`]?
|
||||
///
|
||||
/// This is determined first by [`Style::wrap_mode`], and then by the layout of this [`Ui`].
|
||||
#[deprecated = "Use `wrap_mode` instead"]
|
||||
pub fn wrap_text(&self) -> bool {
|
||||
self.wrap_mode() == TextWrapMode::Wrap
|
||||
}
|
||||
|
||||
/// How to vertically align text
|
||||
#[inline]
|
||||
pub fn text_valign(&self) -> Align {
|
||||
@@ -1063,18 +930,6 @@ impl Ui {
|
||||
)
|
||||
}
|
||||
|
||||
/// Deprecated: use [`Self::interact`] instead.
|
||||
#[deprecated = "The contains_pointer argument is ignored. Use `ui.interact` instead."]
|
||||
pub fn interact_with_hovered(
|
||||
&self,
|
||||
rect: Rect,
|
||||
_contains_pointer: bool,
|
||||
id: Id,
|
||||
sense: Sense,
|
||||
) -> Response {
|
||||
self.interact(rect, id, sense)
|
||||
}
|
||||
|
||||
/// Read the [`Ui`]'s background [`Response`].
|
||||
/// Its [`Sense`] will be based on the [`UiBuilder::sense`] used to create this [`Ui`].
|
||||
///
|
||||
@@ -1086,7 +941,7 @@ impl Ui {
|
||||
pub fn response(&self) -> Response {
|
||||
// This is the inverse of Context::read_response. We prefer a response
|
||||
// based on last frame's widget rect since the one from this frame is Rect::NOTHING until
|
||||
// Ui::interact_bg is called or the Ui is dropped.
|
||||
// Ui::remember_min_rect is called or the Ui is dropped.
|
||||
let mut response = self
|
||||
.ctx()
|
||||
.viewport(|viewport| {
|
||||
@@ -1137,16 +992,6 @@ impl Ui {
|
||||
response
|
||||
}
|
||||
|
||||
/// Interact with the background of this [`Ui`],
|
||||
/// i.e. behind all the widgets.
|
||||
///
|
||||
/// The rectangle of the [`Response`] (and interactive area) will be [`Self::min_rect`].
|
||||
#[deprecated = "Use UiBuilder::sense with Ui::response instead"]
|
||||
pub fn interact_bg(&self, sense: Sense) -> Response {
|
||||
// This will update the WidgetRect that was first created in `Ui::new`.
|
||||
self.interact(self.min_rect(), self.unique_id, sense)
|
||||
}
|
||||
|
||||
/// Is the pointer (mouse/touch) above this rectangle in this [`Ui`]?
|
||||
///
|
||||
/// The `clip_rect` and layer of this [`Ui`] will be respected, so, for instance,
|
||||
@@ -1499,34 +1344,6 @@ impl Ui {
|
||||
)
|
||||
}
|
||||
|
||||
/// Allocated the given rectangle and then adds content to that rectangle.
|
||||
///
|
||||
/// If the contents overflow, more space will be allocated.
|
||||
/// When finished, the amount of space actually used (`min_rect`) will be allocated.
|
||||
/// So you can request a lot of space and then use less.
|
||||
#[deprecated = "Use `allocate_new_ui` instead"]
|
||||
pub fn allocate_ui_at_rect<R>(
|
||||
&mut self,
|
||||
max_rect: Rect,
|
||||
add_contents: impl FnOnce(&mut Self) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
self.scope_builder(UiBuilder::new().max_rect(max_rect), add_contents)
|
||||
}
|
||||
|
||||
/// Allocated space (`UiBuilder::max_rect`) and then add content to it.
|
||||
///
|
||||
/// If the contents overflow, more space will be allocated.
|
||||
/// When finished, the amount of space actually used (`min_rect`) will be allocated in the parent.
|
||||
/// So you can request a lot of space and then use less.
|
||||
#[deprecated = "Use `scope_builder` instead"]
|
||||
pub fn allocate_new_ui<R>(
|
||||
&mut self,
|
||||
ui_builder: UiBuilder,
|
||||
add_contents: impl FnOnce(&mut Self) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
self.scope_dyn(ui_builder, Box::new(add_contents))
|
||||
}
|
||||
|
||||
/// Convenience function to get a region to paint on.
|
||||
///
|
||||
/// Note that egui uses screen coordinates for everything.
|
||||
@@ -1817,7 +1634,7 @@ impl Ui {
|
||||
/// If you call `add_visible` from within an already invisible [`Ui`],
|
||||
/// the widget will always be invisible, even if the `visible` argument is true.
|
||||
///
|
||||
/// See also [`Self::add_visible_ui`], [`Self::set_visible`] and [`Self::is_visible`].
|
||||
/// See also [`Self::set_invisible`] and [`Self::is_visible`].
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
@@ -1842,38 +1659,6 @@ impl Ui {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a section that is possibly invisible, i.e. greyed out and non-interactive.
|
||||
///
|
||||
/// An invisible ui still takes up the same space as if it were visible.
|
||||
///
|
||||
/// If you call `add_visible_ui` from within an already invisible [`Ui`],
|
||||
/// the result will always be invisible, even if the `visible` argument is true.
|
||||
///
|
||||
/// See also [`Self::add_visible`], [`Self::set_visible`] and [`Self::is_visible`].
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// # let mut visible = true;
|
||||
/// ui.checkbox(&mut visible, "Show subsection");
|
||||
/// ui.add_visible_ui(visible, |ui| {
|
||||
/// ui.label("Maybe you see this, maybe you don't!");
|
||||
/// });
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use 'ui.scope_builder' instead"]
|
||||
pub fn add_visible_ui<R>(
|
||||
&mut self,
|
||||
visible: bool,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
let mut ui_builder = UiBuilder::new();
|
||||
if !visible {
|
||||
ui_builder = ui_builder.invisible();
|
||||
}
|
||||
self.scope_builder(ui_builder, add_contents)
|
||||
}
|
||||
|
||||
/// Add extra space before the next widget.
|
||||
///
|
||||
/// The direction is dependent on the layout.
|
||||
@@ -2381,21 +2166,6 @@ impl Ui {
|
||||
self.scope_dyn(UiBuilder::new().id_salt(id_salt), Box::new(add_contents))
|
||||
}
|
||||
|
||||
/// Push another level onto the [`UiStack`].
|
||||
///
|
||||
/// You can use this, for instance, to tag a group of widgets.
|
||||
#[deprecated = "Use 'ui.scope_builder' instead"]
|
||||
pub fn push_stack_info<R>(
|
||||
&mut self,
|
||||
ui_stack_info: UiStackInfo,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
self.scope_dyn(
|
||||
UiBuilder::new().ui_stack_info(ui_stack_info),
|
||||
Box::new(add_contents),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a scoped child ui.
|
||||
///
|
||||
/// You can use this to temporarily change the [`Style`] of a sub-region, for instance:
|
||||
@@ -2436,26 +2206,6 @@ impl Ui {
|
||||
InnerResponse::new(ret, response)
|
||||
}
|
||||
|
||||
/// Redirect shapes to another paint layer.
|
||||
///
|
||||
/// ```
|
||||
/// # use egui::{LayerId, Order, Id};
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// let layer_id = LayerId::new(Order::Tooltip, Id::new("my_floating_ui"));
|
||||
/// ui.with_layer_id(layer_id, |ui| {
|
||||
/// ui.label("This is now in a different layer");
|
||||
/// });
|
||||
/// # });
|
||||
/// ```
|
||||
#[deprecated = "Use ui.scope_builder(UiBuilder::new().layer_id(…), …) instead"]
|
||||
pub fn with_layer_id<R>(
|
||||
&mut self,
|
||||
layer_id: LayerId,
|
||||
add_contents: impl FnOnce(&mut Self) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
self.scope_builder(UiBuilder::new().layer_id(layer_id), add_contents)
|
||||
}
|
||||
|
||||
/// A [`CollapsingHeader`] that starts out collapsed.
|
||||
///
|
||||
/// The name must be unique within the current parent,
|
||||
@@ -3009,22 +2759,6 @@ impl Ui {
|
||||
|
||||
/// # Menus
|
||||
impl Ui {
|
||||
/// Close the menu we are in (including submenus), if any.
|
||||
///
|
||||
/// See also: [`Self::menu_button`] and [`Response::context_menu`].
|
||||
#[deprecated = "Use `ui.close()` or `ui.close_kind(UiKind::Menu)` instead"]
|
||||
pub fn close_menu(&self) {
|
||||
self.close_kind(UiKind::Menu);
|
||||
}
|
||||
|
||||
#[expect(deprecated)]
|
||||
pub(crate) fn set_menu_state(
|
||||
&mut self,
|
||||
menu_state: Option<Arc<RwLock<crate::menu::MenuState>>>,
|
||||
) {
|
||||
self.menu_state = menu_state;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Create a menu button that when clicked will show the given menu.
|
||||
///
|
||||
|
||||
@@ -8,7 +8,3 @@ pub use id_type_map::IdTypeMap;
|
||||
|
||||
pub use epaint::emath::History;
|
||||
pub use epaint::util::{hash, hash_with};
|
||||
|
||||
/// Deprecated alias for [`crate::cache`].
|
||||
#[deprecated = "Use egui::cache instead"]
|
||||
pub use crate::cache;
|
||||
|
||||
@@ -1201,7 +1201,7 @@ impl ViewportCommand {
|
||||
|
||||
/// Describes a viewport, i.e. a native window.
|
||||
///
|
||||
/// This is returned by [`crate::Context::run`] on each frame, and should be applied
|
||||
/// This is returned by [`crate::Context::run_ui`] on each frame, and should be applied
|
||||
/// by the integration.
|
||||
#[derive(Clone)]
|
||||
pub struct ViewportOutput {
|
||||
|
||||
@@ -156,7 +156,7 @@ impl RichText {
|
||||
/// Default: 0.0.
|
||||
///
|
||||
/// For even text it is recommended you round this to an even number of _pixels_,
|
||||
/// e.g. using [`crate::Painter::round_to_pixel`].
|
||||
/// e.g. using [`emath::GuiRounding`].
|
||||
#[inline]
|
||||
pub fn extra_letter_spacing(mut self, extra_letter_spacing: f32) -> Self {
|
||||
self.extra_letter_spacing = extra_letter_spacing;
|
||||
@@ -170,7 +170,7 @@ impl RichText {
|
||||
/// If `None` (the default), the line height is determined by the font.
|
||||
///
|
||||
/// For even text it is recommended you round this to an even number of _pixels_,
|
||||
/// e.g. using [`crate::Painter::round_to_pixel`].
|
||||
/// e.g. using [`emath::GuiRounding`].
|
||||
#[inline]
|
||||
pub fn line_height(mut self, line_height: Option<f32>) -> Self {
|
||||
self.line_height = line_height;
|
||||
|
||||
@@ -200,12 +200,6 @@ impl<'a> Button<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[deprecated = "Renamed to `corner_radius`"]
|
||||
pub fn rounding(self, corner_radius: impl Into<CornerRadius>) -> Self {
|
||||
self.corner_radius(corner_radius)
|
||||
}
|
||||
|
||||
/// If true, the tint of the image is multiplied by the widget text color.
|
||||
///
|
||||
/// This makes sense for images that are white, that should have the same color as the text color.
|
||||
|
||||
@@ -91,16 +91,6 @@ impl<'a> DragValue<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets valid range for the value.
|
||||
///
|
||||
/// By default all values are clamped to this range, even when not interacted with.
|
||||
/// You can change this behavior by passing `false` to [`Self::clamp_existing_to_range`].
|
||||
#[deprecated = "Use `range` instead"]
|
||||
#[inline]
|
||||
pub fn clamp_range<Num: emath::Numeric>(self, range: RangeInclusive<Num>) -> Self {
|
||||
self.range(range)
|
||||
}
|
||||
|
||||
/// Sets valid range for dragging the value.
|
||||
///
|
||||
/// By default all values are clamped to this range, even when not interacted with.
|
||||
@@ -157,12 +147,6 @@ impl<'a> DragValue<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[deprecated = "Renamed clamp_existing_to_range"]
|
||||
pub fn clamp_to_range(self, clamp_to_range: bool) -> Self {
|
||||
self.clamp_existing_to_range(clamp_to_range)
|
||||
}
|
||||
|
||||
/// Show a prefix before the number, e.g. "x: "
|
||||
#[inline]
|
||||
pub fn prefix(mut self, prefix: impl IntoAtoms<'a>) -> Self {
|
||||
|
||||
@@ -256,18 +256,6 @@ impl<'a> Image<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Round the corners of the image.
|
||||
///
|
||||
/// The default is no rounding ([`CornerRadius::ZERO`]).
|
||||
///
|
||||
/// Due to limitations in the current implementation,
|
||||
/// this will turn off any rotation of the image.
|
||||
#[inline]
|
||||
#[deprecated = "Renamed to `corner_radius`"]
|
||||
pub fn rounding(self, corner_radius: impl Into<CornerRadius>) -> Self {
|
||||
self.corner_radius(corner_radius)
|
||||
}
|
||||
|
||||
/// Show a spinner when the image is loading.
|
||||
///
|
||||
/// By default this uses the value of [`crate::Visuals::image_loading_spinners`].
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
use crate::{
|
||||
Color32, CornerRadius, Image, Rect, Response, Sense, Ui, Vec2, Widget, WidgetInfo, WidgetType,
|
||||
widgets,
|
||||
};
|
||||
|
||||
/// A clickable image within a frame.
|
||||
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
|
||||
#[derive(Clone, Debug)]
|
||||
#[deprecated(since = "0.33.0", note = "Use egui::Button::image instead")]
|
||||
pub struct ImageButton<'a> {
|
||||
pub(crate) image: Image<'a>,
|
||||
sense: Sense,
|
||||
frame: bool,
|
||||
selected: bool,
|
||||
alt_text: Option<String>,
|
||||
}
|
||||
|
||||
#[expect(deprecated, reason = "Deprecated in egui 0.33.0")]
|
||||
impl<'a> ImageButton<'a> {
|
||||
pub fn new(image: impl Into<Image<'a>>) -> Self {
|
||||
Self {
|
||||
image: image.into(),
|
||||
sense: Sense::click(),
|
||||
frame: true,
|
||||
selected: false,
|
||||
alt_text: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Select UV range. Default is (0,0) in top-left, (1,1) bottom right.
|
||||
#[inline]
|
||||
pub fn uv(mut self, uv: impl Into<Rect>) -> Self {
|
||||
self.image = self.image.uv(uv);
|
||||
self
|
||||
}
|
||||
|
||||
/// Multiply image color with this. Default is WHITE (no tint).
|
||||
#[inline]
|
||||
pub fn tint(mut self, tint: impl Into<Color32>) -> Self {
|
||||
self.image = self.image.tint(tint);
|
||||
self
|
||||
}
|
||||
|
||||
/// If `true`, mark this button as "selected".
|
||||
#[inline]
|
||||
pub fn selected(mut self, selected: bool) -> Self {
|
||||
self.selected = selected;
|
||||
self
|
||||
}
|
||||
|
||||
/// Turn off the frame
|
||||
#[inline]
|
||||
pub fn frame(mut self, frame: bool) -> Self {
|
||||
self.frame = frame;
|
||||
self
|
||||
}
|
||||
|
||||
/// By default, buttons senses clicks.
|
||||
/// Change this to a drag-button with `Sense::drag()`.
|
||||
#[inline]
|
||||
pub fn sense(mut self, sense: Sense) -> Self {
|
||||
self.sense = sense;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set rounding for the `ImageButton`.
|
||||
///
|
||||
/// If the underlying image already has rounding, this
|
||||
/// will override that value.
|
||||
#[inline]
|
||||
pub fn corner_radius(mut self, corner_radius: impl Into<CornerRadius>) -> Self {
|
||||
self.image = self.image.corner_radius(corner_radius.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set rounding for the `ImageButton`.
|
||||
///
|
||||
/// If the underlying image already has rounding, this
|
||||
/// will override that value.
|
||||
#[inline]
|
||||
#[deprecated = "Renamed to `corner_radius`"]
|
||||
pub fn rounding(self, corner_radius: impl Into<CornerRadius>) -> Self {
|
||||
self.corner_radius(corner_radius)
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(deprecated, reason = "Deprecated in egui 0.33.0")]
|
||||
impl Widget for ImageButton<'_> {
|
||||
fn ui(self, ui: &mut Ui) -> Response {
|
||||
let padding = if self.frame {
|
||||
// so we can see that it is a button:
|
||||
Vec2::splat(ui.spacing().button_padding.x)
|
||||
} else {
|
||||
Vec2::ZERO
|
||||
};
|
||||
|
||||
let available_size_for_image = ui.available_size() - 2.0 * padding;
|
||||
let tlr = self.image.load_for_size(ui.ctx(), available_size_for_image);
|
||||
let image_source_size = tlr.as_ref().ok().and_then(|t| t.size());
|
||||
let image_size = self
|
||||
.image
|
||||
.calc_size(available_size_for_image, image_source_size);
|
||||
|
||||
let padded_size = image_size + 2.0 * padding;
|
||||
let (rect, response) = ui.allocate_exact_size(padded_size, self.sense);
|
||||
response.widget_info(|| {
|
||||
let mut info = WidgetInfo::new(WidgetType::Button);
|
||||
info.label = self.alt_text.clone();
|
||||
info
|
||||
});
|
||||
|
||||
if ui.is_rect_visible(rect) {
|
||||
let (expansion, rounding, fill, stroke) = if self.selected {
|
||||
let selection = ui.visuals().selection;
|
||||
(
|
||||
Vec2::ZERO,
|
||||
self.image.image_options().corner_radius,
|
||||
selection.bg_fill,
|
||||
selection.stroke,
|
||||
)
|
||||
} else if self.frame {
|
||||
let visuals = ui.style().interact(&response);
|
||||
let expansion = Vec2::splat(visuals.expansion);
|
||||
(
|
||||
expansion,
|
||||
self.image.image_options().corner_radius,
|
||||
visuals.weak_bg_fill,
|
||||
visuals.bg_stroke,
|
||||
)
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
// Draw frame background (for transparent images):
|
||||
ui.painter()
|
||||
.rect_filled(rect.expand2(expansion), rounding, fill);
|
||||
|
||||
let image_rect = ui
|
||||
.layout()
|
||||
.align_size_within_rect(image_size, rect.shrink2(padding));
|
||||
// let image_rect = image_rect.expand2(expansion); // can make it blurry, so let's not
|
||||
let image_options = self.image.image_options().clone();
|
||||
|
||||
widgets::image::paint_texture_load_result(
|
||||
ui,
|
||||
&tlr,
|
||||
image_rect,
|
||||
None,
|
||||
&image_options,
|
||||
self.alt_text.as_deref(),
|
||||
);
|
||||
|
||||
// Draw frame outline:
|
||||
ui.painter().rect_stroke(
|
||||
rect.expand2(expansion),
|
||||
rounding,
|
||||
stroke,
|
||||
epaint::StrokeKind::Inside,
|
||||
);
|
||||
}
|
||||
|
||||
widgets::image::texture_load_result_response(&self.image.source(ui.ctx()), &tlr, response)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
//! * `ui.add(Label::new("Text").text_color(color::red));`
|
||||
//! * `if ui.add(Button::new("Click me")).clicked() { … }`
|
||||
|
||||
use crate::{Response, Ui, epaint};
|
||||
use crate::{Response, Ui};
|
||||
|
||||
mod button;
|
||||
mod checkbox;
|
||||
@@ -12,19 +12,14 @@ pub mod color_picker;
|
||||
pub(crate) mod drag_value;
|
||||
mod hyperlink;
|
||||
mod image;
|
||||
mod image_button;
|
||||
mod label;
|
||||
mod progress_bar;
|
||||
mod radio_button;
|
||||
mod selected_label;
|
||||
mod separator;
|
||||
mod slider;
|
||||
mod spinner;
|
||||
pub mod text_edit;
|
||||
|
||||
#[expect(deprecated)]
|
||||
pub use self::selected_label::SelectableLabel;
|
||||
#[expect(deprecated, reason = "Deprecated in egui 0.33.0")]
|
||||
pub use self::{
|
||||
button::Button,
|
||||
checkbox::Checkbox,
|
||||
@@ -34,7 +29,6 @@ pub use self::{
|
||||
FrameDurations, Image, ImageFit, ImageOptions, ImageSize, ImageSource,
|
||||
decode_animated_image_uri, has_gif_magic_header, has_webp_header, paint_texture_at,
|
||||
},
|
||||
image_button::ImageButton,
|
||||
label::Label,
|
||||
progress_bar::ProgressBar,
|
||||
radio_button::RadioButton,
|
||||
@@ -126,14 +120,6 @@ pub fn reset_button_with<T: PartialEq>(ui: &mut Ui, value: &mut T, text: &str, r
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[deprecated = "Use `ui.add(&mut stroke)` instead"]
|
||||
pub fn stroke_ui(ui: &mut crate::Ui, stroke: &mut epaint::Stroke, text: &str) {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(text);
|
||||
ui.add(stroke);
|
||||
});
|
||||
}
|
||||
|
||||
/// Show a small button to switch to/from dark/light mode (globally).
|
||||
pub fn global_theme_preference_switch(ui: &mut Ui) {
|
||||
if let Some(new_theme) = ui.ctx().theme().small_toggle_button(ui) {
|
||||
@@ -147,15 +133,3 @@ pub fn global_theme_preference_buttons(ui: &mut Ui) {
|
||||
theme_preference.radio_buttons(ui);
|
||||
ui.ctx().set_theme(theme_preference);
|
||||
}
|
||||
|
||||
/// Show a small button to switch to/from dark/light mode (globally).
|
||||
#[deprecated = "Use global_theme_preference_switch instead"]
|
||||
pub fn global_dark_light_mode_switch(ui: &mut Ui) {
|
||||
global_theme_preference_switch(ui);
|
||||
}
|
||||
|
||||
/// Show larger buttons for switching between light and dark mode (globally).
|
||||
#[deprecated = "Use global_theme_preference_buttons instead"]
|
||||
pub fn global_dark_light_mode_buttons(ui: &mut Ui) {
|
||||
global_theme_preference_buttons(ui);
|
||||
}
|
||||
|
||||
@@ -94,12 +94,6 @@ impl ProgressBar {
|
||||
self.corner_radius = Some(corner_radius.into());
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[deprecated = "Renamed to `corner_radius`"]
|
||||
pub fn rounding(self, corner_radius: impl Into<CornerRadius>) -> Self {
|
||||
self.corner_radius(corner_radius)
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for ProgressBar {
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#![expect(deprecated, clippy::new_ret_no_self)]
|
||||
|
||||
use crate::WidgetText;
|
||||
|
||||
#[deprecated = "Use `Button::selectable()` instead"]
|
||||
pub struct SelectableLabel {}
|
||||
|
||||
impl SelectableLabel {
|
||||
#[deprecated = "Use `Button::selectable()` instead"]
|
||||
pub fn new(selected: bool, text: impl Into<WidgetText>) -> super::Button<'static> {
|
||||
crate::Button::selectable(selected, text)
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ pub enum SliderClamping {
|
||||
///
|
||||
/// The slider range defines the values you get when pulling the slider to the far edges.
|
||||
/// By default all values are clamped to this range, even when not interacted with.
|
||||
/// You can change this behavior by passing `false` to [`Slider::clamp_to_range`].
|
||||
/// You can change this behavior by passing `false` to [`Slider::clamping`].
|
||||
///
|
||||
/// The range can include any numbers, and go from low-to-high or from high-to-low.
|
||||
///
|
||||
@@ -288,16 +288,6 @@ impl<'a> Slider<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[deprecated = "Use `slider.clamping(…) instead"]
|
||||
pub fn clamp_to_range(self, clamp_to_range: bool) -> Self {
|
||||
self.clamping(if clamp_to_range {
|
||||
SliderClamping::Always
|
||||
} else {
|
||||
SliderClamping::Never
|
||||
})
|
||||
}
|
||||
|
||||
/// Turn smart aim on/off. Default is ON.
|
||||
/// There is almost no point in turning this off.
|
||||
#[inline]
|
||||
|
||||
@@ -51,14 +51,6 @@ impl<'a> DatePickerButton<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Add id source.
|
||||
/// Must be set if multiple date picker buttons are in the same Ui.
|
||||
#[inline]
|
||||
#[deprecated = "Renamed id_salt"]
|
||||
pub fn id_source(self, id_salt: &'a str) -> Self {
|
||||
self.id_salt(id_salt)
|
||||
}
|
||||
|
||||
/// Show combo boxes in date picker popup. (Default: true)
|
||||
#[inline]
|
||||
pub fn combo_boxes(mut self, combo_boxes: bool) -> Self {
|
||||
|
||||
@@ -270,15 +270,6 @@ impl<'a> TableBuilder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Give this table a unique id within the parent [`Ui`].
|
||||
///
|
||||
/// This is required if you have multiple tables in the same [`Ui`].
|
||||
#[inline]
|
||||
#[deprecated = "Renamed id_salt"]
|
||||
pub fn id_source(self, id_salt: impl std::hash::Hash) -> Self {
|
||||
self.id_salt(id_salt)
|
||||
}
|
||||
|
||||
/// Give this table a unique id within the parent [`Ui`].
|
||||
///
|
||||
/// This is required if you have multiple tables in the same [`Ui`].
|
||||
@@ -329,7 +320,7 @@ impl<'a> TableBuilder<'a> {
|
||||
|
||||
/// Enables scrolling the table's contents using mouse drag (default: `true`).
|
||||
///
|
||||
/// See [`ScrollArea::drag_to_scroll`] for more.
|
||||
/// See [`ScrollArea::scroll_source`] for more.
|
||||
#[inline]
|
||||
pub fn drag_to_scroll(mut self, drag_to_scroll: bool) -> Self {
|
||||
self.scroll_options.drag_to_scroll = drag_to_scroll;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use egui::Frame;
|
||||
|
||||
type AppKindContextState<'a, State> = Box<dyn FnMut(&egui::Context, &mut State) + 'a>;
|
||||
type AppKindUiState<'a, State> = Box<dyn FnMut(&mut egui::Ui, &mut State) + 'a>;
|
||||
type AppKindContext<'a> = Box<dyn FnMut(&egui::Context) + 'a>;
|
||||
type AppKindUi<'a> = Box<dyn FnMut(&mut egui::Ui) + 'a>;
|
||||
|
||||
/// In order to access the [`eframe::App`] trait from the generic `State`, we store a function pointer
|
||||
@@ -13,9 +11,7 @@ type AppKindUi<'a> = Box<dyn FnMut(&mut egui::Ui) + 'a>;
|
||||
type AppKindEframe<'a, State> = (fn(&mut State) -> &mut dyn eframe::App, eframe::Frame);
|
||||
|
||||
pub(crate) enum AppKind<'a, State> {
|
||||
Context(AppKindContext<'a>),
|
||||
Ui(AppKindUi<'a>),
|
||||
ContextState(AppKindContextState<'a, State>),
|
||||
UiState(AppKindUiState<'a, State>),
|
||||
#[cfg(feature = "eframe")]
|
||||
Eframe(AppKindEframe<'a, State>),
|
||||
@@ -29,25 +25,12 @@ impl<State> AppKind<'_, State> {
|
||||
sizing_pass: bool,
|
||||
) -> Option<egui::Response> {
|
||||
match self {
|
||||
AppKind::Context(f) => {
|
||||
debug_assert!(!sizing_pass, "Context closures cannot do a sizing pass");
|
||||
f(ui);
|
||||
None
|
||||
}
|
||||
AppKind::ContextState(f) => {
|
||||
debug_assert!(!sizing_pass, "Context closures cannot do a sizing pass");
|
||||
f(ui, state);
|
||||
None
|
||||
}
|
||||
#[cfg(feature = "eframe")]
|
||||
AppKind::Eframe((get_app, frame)) => {
|
||||
let app = get_app(state);
|
||||
|
||||
app.logic(ui, frame);
|
||||
|
||||
#[expect(deprecated)]
|
||||
app.update(ui, frame);
|
||||
|
||||
app.ui(ui, frame);
|
||||
|
||||
None
|
||||
@@ -74,8 +57,9 @@ impl<State> AppKind<'_, State> {
|
||||
.show(ui, |ui| match self {
|
||||
AppKind::Ui(f) => f(ui),
|
||||
AppKind::UiState(f) => f(ui, state),
|
||||
_ => unreachable!(
|
||||
"run_ui should only be called with AppKind::Ui or AppKind UiState"
|
||||
#[cfg(feature = "eframe")]
|
||||
AppKind::Eframe(_) => unreachable!(
|
||||
"run_ui should only be called with AppKind::Ui or AppKind::UiState"
|
||||
),
|
||||
});
|
||||
})
|
||||
|
||||
@@ -159,46 +159,10 @@ impl<State> HarnessBuilder<State> {
|
||||
self.renderer(crate::wgpu::WgpuTestRenderer::from_setup(setup))
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given app closure and a state.
|
||||
///
|
||||
/// The app closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you don't need to create Windows / Panels, you can use [`HarnessBuilder::build_ui`] instead.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui::CentralPanel;
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
/// let checked = false;
|
||||
/// let mut harness = Harness::builder()
|
||||
/// .with_size(egui::Vec2::new(300.0, 200.0))
|
||||
/// .build_state(|ctx, checked| {
|
||||
/// CentralPanel::default().show(ctx, |ui| {
|
||||
/// ui.checkbox(checked, "Check me!");
|
||||
/// });
|
||||
/// }, checked);
|
||||
///
|
||||
/// harness.get_by_label("Check me!").click();
|
||||
/// harness.run();
|
||||
///
|
||||
/// assert_eq!(*harness.state(), true);
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[deprecated = "use `build_ui_state` instead"]
|
||||
pub fn build_state<'a>(
|
||||
self,
|
||||
app: impl FnMut(&egui::Context, &mut State) + 'a,
|
||||
state: State,
|
||||
) -> Harness<'a, State> {
|
||||
Harness::from_builder(self, AppKind::ContextState(Box::new(app)), state, None)
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given ui closure and a state.
|
||||
///
|
||||
/// The ui closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you need to create Windows / Panels, you can use [`HarnessBuilder::build`] instead.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
@@ -249,37 +213,10 @@ impl<State> HarnessBuilder<State> {
|
||||
}
|
||||
|
||||
impl HarnessBuilder {
|
||||
/// Create a new Harness with the given app closure.
|
||||
///
|
||||
/// The app closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you don't need to create Windows / Panels, you can use [`HarnessBuilder::build_ui`] instead.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui::CentralPanel;
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
/// let mut harness = Harness::builder()
|
||||
/// .with_size(egui::Vec2::new(300.0, 200.0))
|
||||
/// .build(|ctx| {
|
||||
/// CentralPanel::default().show(ctx, |ui| {
|
||||
/// ui.label("Hello, world!");
|
||||
/// });
|
||||
/// });
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
#[deprecated = "use `build_ui` instead"]
|
||||
pub fn build<'a>(self, app: impl FnMut(&egui::Context) + 'a) -> Harness<'a> {
|
||||
Harness::from_builder(self, AppKind::Context(Box::new(app)), (), None)
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given ui closure.
|
||||
///
|
||||
/// The ui closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you need to create Windows / Panels, you can use [`HarnessBuilder::build`] instead.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
|
||||
@@ -60,7 +60,7 @@ impl Display for ExceededMaxStepsError {
|
||||
|
||||
/// The test Harness. This contains everything needed to run the test.
|
||||
///
|
||||
/// Create a new Harness using [`Harness::new`] or [`Harness::builder`].
|
||||
/// Create a new Harness using [`Harness::new_ui`] or [`Harness::builder`].
|
||||
///
|
||||
/// The [Harness] has a optional generic state that can be used to pass data to the app / ui closure.
|
||||
/// In _most cases_ it should be fine to just store the state in the closure itself.
|
||||
@@ -185,43 +185,10 @@ impl<'a, State> Harness<'a, State> {
|
||||
HarnessBuilder::default()
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given app closure and a state.
|
||||
///
|
||||
/// The app closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you don't need to create Windows / Panels, you can use [`Harness::new_ui`] instead.
|
||||
///
|
||||
/// If you e.g. want to customize the size of the window, you can use [`Harness::builder`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui::CentralPanel;
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
/// let mut checked = false;
|
||||
/// let mut harness = Harness::new_state(|ctx, checked| {
|
||||
/// CentralPanel::default().show(ctx, |ui| {
|
||||
/// ui.checkbox(checked, "Check me!");
|
||||
/// });
|
||||
/// }, checked);
|
||||
///
|
||||
/// harness.get_by_label("Check me!").click();
|
||||
/// harness.run();
|
||||
///
|
||||
/// assert_eq!(*harness.state(), true);
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[deprecated = "use `new_ui_state` instead"]
|
||||
pub fn new_state(app: impl FnMut(&egui::Context, &mut State) + 'a, state: State) -> Self {
|
||||
#[expect(deprecated)]
|
||||
Self::builder().build_state(app, state)
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given ui closure and a state.
|
||||
///
|
||||
/// The ui closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you need to create Windows / Panels, you can use [`Harness::new`] instead.
|
||||
///
|
||||
/// If you e.g. want to customize the size of the ui, you can use [`Harness::builder`].
|
||||
///
|
||||
/// # Example
|
||||
@@ -714,48 +681,15 @@ impl<'a, State> Harness<'a, State> {
|
||||
queue: &self.queued_events,
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated = "Use `Harness::root` instead."]
|
||||
pub fn node(&self) -> Node<'_> {
|
||||
self.root()
|
||||
}
|
||||
}
|
||||
|
||||
/// Utilities for stateless harnesses.
|
||||
impl<'a> Harness<'a> {
|
||||
/// Create a new Harness with the given app closure.
|
||||
/// Use the [`Harness::run`], [`Harness::step`], etc... methods to run the app.
|
||||
///
|
||||
/// The app closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you don't need to create Windows / Panels, you can use [`Harness::new_ui`] instead.
|
||||
///
|
||||
/// If you e.g. want to customize the size of the window, you can use [`Harness::builder`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui::CentralPanel;
|
||||
/// # use egui_kittest::Harness;
|
||||
/// let mut harness = Harness::new(|ctx| {
|
||||
/// CentralPanel::default().show(ctx, |ui| {
|
||||
/// ui.label("Hello, world!");
|
||||
/// });
|
||||
/// });
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[deprecated = "use `new_ui` instead"]
|
||||
pub fn new(app: impl FnMut(&egui::Context) + 'a) -> Self {
|
||||
#[expect(deprecated)]
|
||||
Self::builder().build(app)
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given ui closure.
|
||||
/// Use the [`Harness::run`], [`Harness::step`], etc... methods to run the app.
|
||||
///
|
||||
/// The ui closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you need to create Windows / Panels, you can use [`Harness::new`] instead.
|
||||
///
|
||||
/// If you e.g. want to customize the size of the ui, you can use [`Harness::builder`].
|
||||
///
|
||||
/// # Example
|
||||
|
||||
@@ -54,11 +54,6 @@ impl Node<'_> {
|
||||
self.click_button(PointerButton::Primary);
|
||||
}
|
||||
|
||||
#[deprecated = "Use `click()` instead."]
|
||||
pub fn simulate_click(&self) {
|
||||
self.click();
|
||||
}
|
||||
|
||||
pub fn click_secondary(&self) {
|
||||
self.click_button(PointerButton::Secondary);
|
||||
}
|
||||
@@ -130,28 +125,6 @@ impl Node<'_> {
|
||||
}));
|
||||
}
|
||||
|
||||
#[deprecated = "Use `Harness::key_down` instead."]
|
||||
pub fn key_down(&self, key: egui::Key) {
|
||||
self.event(egui::Event::Key {
|
||||
key,
|
||||
pressed: true,
|
||||
modifiers: Modifiers::default(),
|
||||
repeat: false,
|
||||
physical_key: None,
|
||||
});
|
||||
}
|
||||
|
||||
#[deprecated = "Use `Harness::key_up` instead."]
|
||||
pub fn key_up(&self, key: egui::Key) {
|
||||
self.event(egui::Event::Key {
|
||||
key,
|
||||
pressed: false,
|
||||
modifiers: Modifiers::default(),
|
||||
repeat: false,
|
||||
physical_key: None,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn type_text(&self, text: &str) {
|
||||
self.event(egui::Event::Text(text.to_owned()));
|
||||
}
|
||||
|
||||
@@ -71,15 +71,9 @@ pub use self::{
|
||||
viewport::ViewportInPixels,
|
||||
};
|
||||
|
||||
#[deprecated = "Renamed to CornerRadius"]
|
||||
pub type Rounding = CornerRadius;
|
||||
|
||||
pub use ecolor::{Color32, Hsva, HsvaGamma, Rgba};
|
||||
pub use emath::{Pos2, Rect, Vec2, pos2, vec2};
|
||||
|
||||
#[deprecated = "Use the ahash crate directly."]
|
||||
pub use ahash;
|
||||
|
||||
pub use ecolor;
|
||||
pub use emath;
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@ pub struct MarginF32 {
|
||||
pub bottom: f32,
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed to MarginF32"]
|
||||
pub type Marginf = MarginF32;
|
||||
|
||||
impl From<Margin> for MarginF32 {
|
||||
#[inline]
|
||||
fn from(margin: Margin) -> Self {
|
||||
@@ -97,18 +94,6 @@ impl MarginF32 {
|
||||
pub fn is_same(&self) -> bool {
|
||||
self.left == self.right && self.left == self.top && self.left == self.bottom
|
||||
}
|
||||
|
||||
#[deprecated = "Use `rect + margin` instead"]
|
||||
#[inline]
|
||||
pub fn expand_rect(&self, rect: Rect) -> Rect {
|
||||
Rect::from_min_max(rect.min - self.left_top(), rect.max + self.right_bottom())
|
||||
}
|
||||
|
||||
#[deprecated = "Use `rect - margin` instead"]
|
||||
#[inline]
|
||||
pub fn shrink_rect(&self, rect: Rect) -> Rect {
|
||||
Rect::from_min_max(rect.min + self.left_top(), rect.max - self.right_bottom())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for MarginF32 {
|
||||
|
||||
@@ -357,12 +357,6 @@ impl Shape {
|
||||
.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[deprecated = "Use `Shape::galley` or `Shape::galley_with_override_text_color` instead"]
|
||||
pub fn galley_with_color(pos: Pos2, galley: Arc<Galley>, text_color: Color32) -> Self {
|
||||
Self::galley_with_override_text_color(pos, galley, text_color)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mesh(mesh: impl Into<Arc<Mesh>>) -> Self {
|
||||
let mesh = mesh.into();
|
||||
|
||||
@@ -1703,16 +1703,6 @@ impl Tessellator {
|
||||
.stroke_open(self.feathering, &stroke.into(), out);
|
||||
}
|
||||
|
||||
#[deprecated = "Use `tessellate_line_segment` instead"]
|
||||
pub fn tessellate_line(
|
||||
&mut self,
|
||||
points: [Pos2; 2],
|
||||
stroke: impl Into<Stroke>,
|
||||
out: &mut Mesh,
|
||||
) {
|
||||
self.tessellate_line_segment(points, stroke, out);
|
||||
}
|
||||
|
||||
/// Tessellate a single [`PathShape`] into a [`Mesh`].
|
||||
///
|
||||
/// * `path_shape`: the path to tessellate.
|
||||
|
||||
Reference in New Issue
Block a user