1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-27 15:13:12 -04:00

Merge branch 'main' into emilk/default_affects_opacity

This commit is contained in:
Emil Ernerfeldt
2025-07-01 13:44:17 +02:00
202 changed files with 853 additions and 592 deletions

View File

@@ -39,7 +39,7 @@ jobs:
with:
profile: minimal
target: wasm32-unknown-unknown
toolchain: 1.84.0
toolchain: 1.85.0
override: true
- uses: Swatinem/rust-cache@v2

View File

@@ -19,7 +19,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.84.0
toolchain: 1.85.0
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:

View File

@@ -18,7 +18,7 @@ jobs:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.84.0
toolchain: 1.85.0
- name: Install packages (Linux)
if: runner.os == 'Linux'
@@ -83,7 +83,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.84.0
toolchain: 1.85.0
targets: wasm32-unknown-unknown
- run: sudo apt-get update && sudo apt-get install libgtk-3-dev libatk1.0-dev
@@ -155,7 +155,7 @@ jobs:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
with:
rust-version: "1.84.0"
rust-version: "1.85.0"
log-level: error
command: check
arguments: --target ${{ matrix.target }}
@@ -170,7 +170,7 @@ jobs:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.84.0
toolchain: 1.85.0
targets: aarch64-linux-android
- name: Set up cargo cache
@@ -191,7 +191,7 @@ jobs:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.84.0
toolchain: 1.85.0
targets: aarch64-apple-ios
- name: Set up cargo cache
@@ -210,7 +210,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.84.0
toolchain: 1.85.0
- name: Set up cargo cache
uses: Swatinem/rust-cache@v2
@@ -234,7 +234,7 @@ jobs:
lfs: true
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.84.0
toolchain: 1.85.0
- name: Set up cargo cache
uses: Swatinem/rust-cache@v2

View File

@@ -21,9 +21,9 @@ members = [
]
[workspace.package]
edition = "2021"
edition = "2024"
license = "MIT OR Apache-2.0"
rust-version = "1.84"
rust-version = "1.85"
version = "0.31.1"
@@ -171,7 +171,6 @@ fn_params_excessive_bools = "warn"
fn_to_numeric_cast_any = "warn"
from_iter_instead_of_collect = "warn"
get_unwrap = "warn"
if_let_mutex = "warn"
implicit_clone = "warn"
implied_bounds_in_impls = "warn"
imprecise_flops = "warn"
@@ -193,6 +192,7 @@ large_stack_frames = "warn"
large_types_passed_by_value = "warn"
let_unit_value = "warn"
linkedlist = "warn"
literal_string_with_formatting_args = "warn"
lossy_float_literal = "warn"
macro_use_imports = "warn"
manual_assert = "warn"

View File

@@ -3,7 +3,7 @@
# -----------------------------------------------------------------------------
# Section identical to scripts/clippy_wasm/clippy.toml:
msrv = "1.84"
msrv = "1.85"
allow-unwrap-in-tests = true

View File

@@ -1,4 +1,4 @@
use super::{linear_f32_from_linear_u8, linear_u8_from_linear_f32, Color32, Hsva, HsvaGamma, Rgba};
use super::{Color32, Hsva, HsvaGamma, Rgba, linear_f32_from_linear_u8, linear_u8_from_linear_f32};
use cint::{Alpha, ColorInterop, EncodedSrgb, Hsv, LinearSrgb, PremultipliedAlpha};
// ---- Color32 ----

View File

@@ -1,4 +1,4 @@
use crate::{fast_round, linear_f32_from_linear_u8, Rgba};
use crate::{Rgba, fast_round, linear_f32_from_linear_u8};
/// This format is used for space-efficient color representation (32 bits).
///

View File

@@ -1,5 +1,5 @@
use crate::{
gamma_u8_from_linear_f32, linear_f32_from_gamma_u8, linear_u8_from_linear_f32, Color32, Rgba,
Color32, Rgba, gamma_u8_from_linear_f32, linear_f32_from_gamma_u8, linear_u8_from_linear_f32,
};
/// Hue, saturation, value, alpha. All in the range [0, 1].

View File

@@ -1,4 +1,4 @@
use crate::{gamma_from_linear, linear_from_gamma, Color32, Hsva, Rgba};
use crate::{Color32, Hsva, Rgba, gamma_from_linear, linear_from_gamma};
/// Like Hsva but with the `v` value (brightness) being gamma corrected
/// so that it is somewhat perceptually even.

View File

@@ -24,7 +24,7 @@ To use on Linux, first run:
sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev
```
You need to either use `edition = "2021"`, or set `resolver = "2"` in the `[workspace]` section of your to-level `Cargo.toml`. See [this link](https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html) for more info.
You need to either use `edition = "2024"`, or set `resolver = "2"` in the `[workspace]` section of your to-level `Cargo.toml`. See [this link](https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html) for more info.
You can opt-in to the using [`egui-wgpu`](https://github.com/emilk/egui/tree/main/crates/egui-wgpu) for rendering by enabling the `wgpu` feature and setting `NativeOptions::renderer` to `Renderer::Wgpu`.

View File

@@ -574,7 +574,9 @@ impl Default for Renderer {
fn default() -> Self {
#[cfg(not(feature = "glow"))]
#[cfg(not(feature = "wgpu"))]
compile_error!("eframe: you must enable at least one of the rendering backend features: 'glow' or 'wgpu'");
compile_error!(
"eframe: you must enable at least one of the rendering backend features: 'glow' or 'wgpu'"
);
#[cfg(feature = "glow")]
#[cfg(not(feature = "wgpu"))]
@@ -617,7 +619,9 @@ impl std::str::FromStr for Renderer {
#[cfg(feature = "wgpu")]
"wgpu" => Ok(Self::Wgpu),
_ => Err(format!("eframe renderer {name:?} is not available. Make sure that the corresponding eframe feature is enabled."))
_ => Err(format!(
"eframe renderer {name:?} is not available. Make sure that the corresponding eframe feature is enabled."
)),
}
}
}

View File

@@ -205,13 +205,18 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
use objc2::ClassType as _;
use objc2_app_kit::{NSApplication, NSImage};
use objc2_foundation::{NSData, NSString};
use objc2_foundation::NSString;
let png_bytes = if let Some(icon_data) = icon_data {
match icon_data.to_png_bytes() {
Ok(png_bytes) => Some(png_bytes),
// Do NOT use png even though creating `NSImage` from it is much easier than from raw images data!
//
// Some MacOS versions have a bug where creating an `NSImage` from a png will cause it to load an arbitrary `libpng.dylib`.
// If this dylib isn't the right version, the application will crash with SIGBUS.
// For details see https://github.com/emilk/egui/issues/7155
let image = if let Some(icon_data) = icon_data {
match icon_data.to_image() {
Ok(image) => Some(image),
Err(err) => {
log::warn!("Failed to convert IconData to png: {err}");
log::warn!("Failed to read icon data: {err}");
return AppIconStatus::NotSetIgnored;
}
}
@@ -220,7 +225,7 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
};
// TODO(madsmtm): Move this into `objc2-app-kit`
extern "C" {
unsafe extern "C" {
static NSApp: Option<&'static NSApplication>;
}
@@ -231,15 +236,41 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
return AppIconStatus::NotSetIgnored;
};
if let Some(png_bytes) = png_bytes {
let data = NSData::from_vec(png_bytes);
if let Some(image) = image {
use objc2_app_kit::{NSBitmapImageRep, NSDeviceRGBColorSpace};
use objc2_foundation::NSSize;
log::trace!("NSImage::initWithData…");
let app_icon = NSImage::initWithData(NSImage::alloc(), &data);
log::trace!(
"NSBitmapImageRep::initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel"
);
let Some(image_rep) = NSBitmapImageRep::initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(
NSBitmapImageRep::alloc(),
[image.as_raw().as_ptr().cast_mut()].as_mut_ptr(),
image.width() as isize,
image.height() as isize,
8, // bits per sample
4, // samples per pixel
true, // has alpha
false, // is not planar
NSDeviceRGBColorSpace,
(image.width() * 4) as isize, // bytes per row
32 // bits per pixel
) else {
log::warn!("Failed to create NSBitmapImageRep from app icon data.");
return AppIconStatus::NotSetIgnored;
};
log::trace!("NSImage::initWithSize");
let app_icon = NSImage::initWithSize(
NSImage::alloc(),
NSSize::new(image.width() as f64, image.height() as f64),
);
log::trace!("NSImage::addRepresentation");
app_icon.addRepresentation(&image_rep);
profiling::scope!("setApplicationIconImage_");
log::trace!("setApplicationIconImage…");
app.setApplicationIconImage(app_icon.as_deref());
app.setApplicationIconImage(Some(&app_icon));
}
// Change the title in the top bar - for python processes this would be again "python" otherwise.

View File

@@ -52,10 +52,10 @@ fn roaming_appdata() -> Option<PathBuf> {
use windows_sys::Win32::Foundation::S_OK;
use windows_sys::Win32::System::Com::CoTaskMemFree;
use windows_sys::Win32::UI::Shell::{
FOLDERID_RoamingAppData, SHGetKnownFolderPath, KF_FLAG_DONT_VERIFY,
FOLDERID_RoamingAppData, KF_FLAG_DONT_VERIFY, SHGetKnownFolderPath,
};
extern "C" {
unsafe extern "C" {
fn wcslen(buf: *const u16) -> usize;
}
let mut path_raw = ptr::null_mut();

View File

@@ -32,13 +32,13 @@ use egui::{
use egui_winit::accesskit_winit;
use crate::{
native::epi_integration::EpiIntegration, App, AppCreator, CreationContext, NativeOptions,
Result, Storage,
App, AppCreator, CreationContext, NativeOptions, Result, Storage,
native::epi_integration::EpiIntegration,
};
use super::{
epi_integration, event_loop_context,
winit_integration::{create_egui_context, EventResult, UserEvent, WinitApp},
winit_integration::{EventResult, UserEvent, WinitApp, create_egui_context},
};
// ----------------------------------------------------------------------------
@@ -959,7 +959,6 @@ impl GlutinWindowContext {
.with_preference(glutin_winit::ApiPreference::FallbackEgl)
.with_window_attributes(Some(egui_winit::create_winit_window_attributes(
egui_ctx,
event_loop,
viewport_builder.clone(),
)));
@@ -1016,7 +1015,9 @@ impl GlutinWindowContext {
let gl_context = match gl_context_result {
Ok(it) => it,
Err(err) => {
log::warn!("Failed to create context using default context attributes {context_attributes:?} due to error: {err}");
log::warn!(
"Failed to create context using default context attributes {context_attributes:?} due to error: {err}"
);
log::debug!(
"Retrying with fallback context attributes: {fallback_context_attributes:?}"
);
@@ -1113,7 +1114,6 @@ impl GlutinWindowContext {
log::debug!("Creating a window for viewport {viewport_id:?}");
let window_attributes = egui_winit::create_winit_window_attributes(
&self.egui_ctx,
event_loop,
viewport.builder.clone(),
);
if window_attributes.transparent()

View File

@@ -10,9 +10,8 @@ use ahash::HashMap;
use super::winit_integration::{UserEvent, WinitApp};
use crate::{
epi,
Result, epi,
native::{event_loop_context, winit_integration::EventResult},
Result,
};
// ----------------------------------------------------------------------------

View File

@@ -25,8 +25,8 @@ use egui_winit::accesskit_winit;
use winit_integration::UserEvent;
use crate::{
native::{epi_integration::EpiIntegration, winit_integration::EventResult},
App, AppCreator, CreationContext, NativeOptions, Result, Storage,
native::{epi_integration::EpiIntegration, winit_integration::EventResult},
};
use super::{epi_integration, event_loop_context, winit_integration, winit_integration::WinitApp};

View File

@@ -1,8 +1,8 @@
use egui::{TexturesDelta, UserData, ViewportCommand};
use crate::{epi, App};
use crate::{App, epi};
use super::{now_sec, text_agent::TextAgent, web_painter::WebPainter as _, NeedRepaint};
use super::{NeedRepaint, now_sec, text_agent::TextAgent, web_painter::WebPainter as _};
pub struct AppRunner {
#[allow(dead_code, clippy::allow_attributes)]

View File

@@ -1,11 +1,10 @@
use crate::web::string_from_js_value;
use super::{
button_from_mouse_event, location_hash, modifiers_from_kb_event, modifiers_from_mouse_event,
modifiers_from_wheel_event, native_pixels_per_point, pos_from_mouse_event,
prefers_color_scheme_dark, primary_touch_pos, push_touches, text_from_keyboard_event,
theme_from_dark_mode, translate_key, AppRunner, Closure, JsCast as _, JsValue, WebRunner,
DEBUG_RESIZE,
AppRunner, Closure, DEBUG_RESIZE, JsCast as _, JsValue, WebRunner, button_from_mouse_event,
location_hash, modifiers_from_kb_event, modifiers_from_mouse_event, modifiers_from_wheel_event,
native_pixels_per_point, pos_from_mouse_event, prefers_color_scheme_dark, primary_touch_pos,
push_touches, text_from_keyboard_event, theme_from_dark_mode, translate_key,
};
use web_sys::{Document, EventTarget, ShadowRoot};
@@ -311,13 +310,17 @@ pub(crate) fn on_keyup(event: web_sys::KeyboardEvent, runner: &mut AppRunner) {
fn install_copy_cut_paste(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), JsValue> {
runner_ref.add_event_listener(target, "paste", |event: web_sys::ClipboardEvent, runner| {
if !runner.input.raw.focused {
return; // The eframe app is not interested
}
if let Some(data) = event.clipboard_data() {
if let Ok(text) = data.get_data("text") {
let text = text.replace("\r\n", "\n");
let mut should_stop_propagation = true;
let mut should_prevent_default = true;
if !text.is_empty() && runner.input.raw.focused {
if !text.is_empty() {
let egui_event = egui::Event::Paste(text);
should_stop_propagation =
(runner.web_options.should_stop_propagation)(&egui_event);
@@ -340,17 +343,19 @@ fn install_copy_cut_paste(runner_ref: &WebRunner, target: &EventTarget) -> Resul
})?;
runner_ref.add_event_listener(target, "cut", |event: web_sys::ClipboardEvent, runner| {
if runner.input.raw.focused {
runner.input.raw.events.push(egui::Event::Cut);
// In Safari we are only allowed to write to the clipboard during the
// event callback, which is why we run the app logic here and now:
runner.logic();
// Make sure we paint the output of the above logic call asap:
runner.needs_repaint.repaint_asap();
if !runner.input.raw.focused {
return; // The eframe app is not interested
}
runner.input.raw.events.push(egui::Event::Cut);
// In Safari we are only allowed to write to the clipboard during the
// event callback, which is why we run the app logic here and now:
runner.logic();
// Make sure we paint the output of the above logic call asap:
runner.needs_repaint.repaint_asap();
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
if (runner.web_options.should_stop_propagation)(&egui::Event::Cut) {
event.stop_propagation();
@@ -362,17 +367,19 @@ fn install_copy_cut_paste(runner_ref: &WebRunner, target: &EventTarget) -> Resul
})?;
runner_ref.add_event_listener(target, "copy", |event: web_sys::ClipboardEvent, runner| {
if runner.input.raw.focused {
runner.input.raw.events.push(egui::Event::Copy);
// In Safari we are only allowed to write to the clipboard during the
// event callback, which is why we run the app logic here and now:
runner.logic();
// Make sure we paint the output of the above logic call asap:
runner.needs_repaint.repaint_asap();
if !runner.input.raw.focused {
return; // The eframe app is not interested
}
runner.input.raw.events.push(egui::Event::Copy);
// In Safari we are only allowed to write to the clipboard during the
// event callback, which is why we run the app logic here and now:
runner.logic();
// Make sure we paint the output of the above logic call asap:
runner.needs_repaint.repaint_asap();
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
if (runner.web_options.should_stop_propagation)(&egui::Event::Copy) {
event.stop_propagation();

View File

@@ -1,4 +1,4 @@
use super::{canvas_content_rect, AppRunner};
use super::{AppRunner, canvas_content_rect};
pub fn pos_from_mouse_event(
canvas: &web_sys::HtmlCanvasElement,

View File

@@ -126,12 +126,17 @@ fn shorten_file_path(file_path: &str) -> &str {
#[test]
fn test_shorten_file_path() {
for (before, after) in [
("/Users/emilk/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.24.1/src/runtime/runtime.rs", "tokio-1.24.1/src/runtime/runtime.rs"),
(
"/Users/emilk/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.24.1/src/runtime/runtime.rs",
"tokio-1.24.1/src/runtime/runtime.rs",
),
("crates/rerun/src/main.rs", "rerun/src/main.rs"),
("/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs", "core/src/ops/function.rs"),
(
"/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs",
"core/src/ops/function.rs",
),
("/weird/path/file.rs", "/weird/path/file.rs"),
]
{
] {
assert_eq!(shorten_file_path(before), after);
}
}

View File

@@ -3,7 +3,7 @@ use std::sync::Arc;
use super::web_painter::WebPainter;
use crate::WebOptions;
use egui::{Event, UserData, ViewportId};
use egui_wgpu::capture::{capture_channel, CaptureReceiver, CaptureSender, CaptureState};
use egui_wgpu::capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel};
use egui_wgpu::{RenderState, SurfaceErrorAction};
use wasm_bindgen::JsValue;
use web_sys::HtmlCanvasElement;

View File

@@ -2,12 +2,12 @@ use std::{cell::RefCell, rc::Rc};
use wasm_bindgen::prelude::*;
use crate::{epi, App};
use crate::{App, epi};
use super::{
AppRunner, PanicHandler,
events::{self, ResizeObserverContext},
text_agent::TextAgent,
AppRunner, PanicHandler,
};
/// This is how `eframe` runs your web application

View File

@@ -1,6 +1,6 @@
use egui::{UserData, ViewportId};
use epaint::ColorImage;
use std::sync::{mpsc, Arc};
use std::sync::{Arc, mpsc};
use wgpu::{BindGroupLayout, MultisampleState, StoreOp};
/// A texture and a buffer for reading the rendered frame back to the cpu.
@@ -196,7 +196,10 @@ impl CaptureState {
wgpu::TextureFormat::Rgba8Unorm => [0, 1, 2, 3],
wgpu::TextureFormat::Bgra8Unorm => [2, 1, 0, 3],
_ => {
log::error!("Screen can't be captured unless the surface format is Rgba8Unorm or Bgra8Unorm. Current surface format is {:?}", format);
log::error!(
"Screen can't be captured unless the surface format is Rgba8Unorm or Bgra8Unorm. Current surface format is {:?}",
format
);
return;
}
};

View File

@@ -3,7 +3,7 @@
use std::{borrow::Cow, num::NonZeroU64, ops::Range};
use ahash::HashMap;
use epaint::{emath::NumExt as _, PaintCallbackInfo, Primitive, Vertex};
use epaint::{PaintCallbackInfo, Primitive, Vertex, emath::NumExt as _};
use wgpu::util::DeviceExt as _;
@@ -909,7 +909,11 @@ impl Renderer {
);
let Some(mut index_buffer_staging) = index_buffer_staging else {
panic!("Failed to create staging buffer for index data. Index count: {index_count}. Required index buffer size: {required_index_buffer_size}. Actual size {} and capacity: {} (bytes)", self.index_buffer.buffer.size(), self.index_buffer.capacity);
panic!(
"Failed to create staging buffer for index data. Index count: {index_count}. Required index buffer size: {required_index_buffer_size}. Actual size {} and capacity: {} (bytes)",
self.index_buffer.buffer.size(),
self.index_buffer.capacity
);
};
let mut index_offset = 0;
@@ -948,7 +952,11 @@ impl Renderer {
);
let Some(mut vertex_buffer_staging) = vertex_buffer_staging else {
panic!("Failed to create staging buffer for vertex data. Vertex count: {vertex_count}. Required vertex buffer size: {required_vertex_buffer_size}. Actual size {} and capacity: {} (bytes)", self.vertex_buffer.buffer.size(), self.vertex_buffer.capacity);
panic!(
"Failed to create staging buffer for vertex data. Vertex count: {vertex_count}. Required vertex buffer size: {required_vertex_buffer_size}. Actual size {} and capacity: {} (bytes)",
self.vertex_buffer.buffer.size(),
self.vertex_buffer.capacity
);
};
let mut vertex_offset = 0;

View File

@@ -1,8 +1,8 @@
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::undocumented_unsafe_blocks)]
use crate::capture::{capture_channel, CaptureReceiver, CaptureSender, CaptureState};
use crate::{renderer, RenderState, SurfaceErrorAction, WgpuConfiguration};
use crate::capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel};
use crate::{RenderState, SurfaceErrorAction, WgpuConfiguration, renderer};
use egui::{Context, Event, UserData, ViewportId, ViewportIdMap, ViewportIdSet};
use std::{num::NonZeroU32, sync::Arc};
@@ -220,7 +220,9 @@ impl Painter {
} else if supported_alpha_modes.contains(&wgpu::CompositeAlphaMode::PostMultiplied) {
wgpu::CompositeAlphaMode::PostMultiplied
} else {
log::warn!("Transparent window was requested, but the active wgpu surface does not support a `CompositeAlphaMode` with transparency.");
log::warn!(
"Transparent window was requested, but the active wgpu surface does not support a `CompositeAlphaMode` with transparency."
);
wgpu::CompositeAlphaMode::Auto
}
} else {
@@ -344,7 +346,9 @@ impl Painter {
height_in_pixels,
);
} else {
log::warn!("Ignoring window resize notification with no surface created via Painter::set_window()");
log::warn!(
"Ignoring window resize notification with no surface created via Painter::set_window()"
);
}
}

View File

@@ -123,7 +123,9 @@ impl Clipboard {
return;
}
log::error!("Copying images is not supported. Enable the 'clipboard' feature of `egui-winit` to enable it.");
log::error!(
"Copying images is not supported. Enable the 'clipboard' feature of `egui-winit` to enable it."
);
_ = image;
}
}

View File

@@ -1566,8 +1566,7 @@ pub fn create_window(
) -> Result<Window, winit::error::OsError> {
profiling::function_scope!();
let window_attributes =
create_winit_window_attributes(egui_ctx, event_loop, viewport_builder.clone());
let window_attributes = create_winit_window_attributes(egui_ctx, viewport_builder.clone());
let window = event_loop.create_window(window_attributes)?;
apply_viewport_builder_to_window(egui_ctx, &window, viewport_builder);
Ok(window)
@@ -1575,28 +1574,10 @@ pub fn create_window(
pub fn create_winit_window_attributes(
egui_ctx: &egui::Context,
event_loop: &ActiveEventLoop,
viewport_builder: ViewportBuilder,
) -> winit::window::WindowAttributes {
profiling::function_scope!();
// We set sizes and positions in egui:s own ui points, which depends on the egui
// zoom_factor and the native pixels per point, so we need to know that here.
// We don't know what monitor the window will appear on though, but
// we'll try to fix that after the window is created in the call to `apply_viewport_builder_to_window`.
let native_pixels_per_point = event_loop
.primary_monitor()
.or_else(|| event_loop.available_monitors().next())
.map_or_else(
|| {
log::debug!("Failed to find a monitor - assuming native_pixels_per_point of 1.0");
1.0
},
|m| m.scale_factor() as f32,
);
let zoom_factor = egui_ctx.zoom_factor();
let pixels_per_point = zoom_factor * native_pixels_per_point;
let ViewportBuilder {
title,
position,
@@ -1672,40 +1653,46 @@ pub fn create_winit_window_attributes(
})
.with_active(active.unwrap_or(true));
// Here and below: we create `LogicalSize` / `LogicalPosition` taking
// zoom factor into account. We don't have a good way to get physical size here,
// and trying to do it anyway leads to weird bugs on Wayland, see:
// https://github.com/emilk/egui/issues/7095#issuecomment-2920545377
// https://github.com/rust-windowing/winit/issues/4266
#[expect(
clippy::disallowed_types,
reason = "zoom factor is manually accounted for"
)]
#[cfg(not(target_os = "ios"))]
if let Some(size) = inner_size {
window_attributes = window_attributes.with_inner_size(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
));
}
{
use winit::dpi::{LogicalPosition, LogicalSize};
let zoom_factor = egui_ctx.zoom_factor();
#[cfg(not(target_os = "ios"))]
if let Some(size) = min_inner_size {
window_attributes = window_attributes.with_min_inner_size(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
));
}
if let Some(size) = inner_size {
window_attributes = window_attributes
.with_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
}
#[cfg(not(target_os = "ios"))]
if let Some(size) = max_inner_size {
window_attributes = window_attributes.with_max_inner_size(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
));
}
if let Some(size) = min_inner_size {
window_attributes = window_attributes
.with_min_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
}
#[cfg(not(target_os = "ios"))]
if let Some(pos) = position {
window_attributes = window_attributes.with_position(PhysicalPosition::new(
pixels_per_point * pos.x,
pixels_per_point * pos.y,
));
if let Some(size) = max_inner_size {
window_attributes = window_attributes
.with_max_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
}
if let Some(pos) = position {
window_attributes = window_attributes.with_position(LogicalPosition::new(
zoom_factor * pos.x,
zoom_factor * pos.y,
));
}
}
#[cfg(target_os = "ios")]
{
// Unused:
_ = egui_ctx;
_ = pixels_per_point;
_ = position;
_ = inner_size;

View File

@@ -1,6 +1,6 @@
use crate::{
emath::{remap_clamp, NumExt as _},
Id, IdMap, InputState,
emath::{NumExt as _, remap_clamp},
};
#[derive(Clone, Default)]

View File

@@ -204,12 +204,17 @@ fn shorten_source_file_path(path: &std::path::Path) -> String {
#[test]
fn test_shorten_path() {
for (before, after) in [
("/Users/emilk/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.24.1/src/runtime/runtime.rs", "tokio-1.24.1/src/runtime/runtime.rs"),
(
"/Users/emilk/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.24.1/src/runtime/runtime.rs",
"tokio-1.24.1/src/runtime/runtime.rs",
),
("crates/rerun/src/main.rs", "rerun/src/main.rs"),
("/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs", "core/src/ops/function.rs"),
(
"/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs",
"core/src/ops/function.rs",
),
("/weird/path/file.rs", "/weird/path/file.rs"),
]
{
] {
use std::str::FromStr as _;
let before = std::path::PathBuf::from_str(before).unwrap();
assert_eq!(shorten_source_file_path(&before), after);

View File

@@ -5,8 +5,8 @@
use emath::GuiRounding as _;
use crate::{
emath, pos2, Align2, Context, Id, InnerResponse, LayerId, Layout, NumExt as _, Order, Pos2,
Rect, Response, Sense, Ui, UiBuilder, UiKind, UiStackInfo, Vec2, WidgetRect, WidgetWithState,
Align2, Context, Id, InnerResponse, LayerId, Layout, NumExt as _, Order, Pos2, Rect, Response,
Sense, Ui, UiBuilder, UiKind, UiStackInfo, Vec2, WidgetRect, WidgetWithState, emath, pos2,
};
/// State of an [`Area`] that is persisted between frames.

View File

@@ -1,9 +1,9 @@
use std::hash::Hash;
use crate::{
emath, epaint, pos2, remap, remap_clamp, vec2, Context, Id, InnerResponse, NumExt as _, Rect,
Response, Sense, Stroke, TextStyle, TextWrapMode, Ui, UiBuilder, UiKind, UiStackInfo, Vec2,
WidgetInfo, WidgetText, WidgetType,
Context, Id, InnerResponse, NumExt as _, Rect, Response, Sense, Stroke, TextStyle,
TextWrapMode, Ui, UiBuilder, UiKind, UiStackInfo, Vec2, WidgetInfo, WidgetText, WidgetType,
emath, epaint, pos2, remap, remap_clamp, vec2,
};
use emath::GuiRounding as _;
use epaint::{Shape, StrokeKind};

View File

@@ -1,9 +1,9 @@
use epaint::Shape;
use crate::{
epaint, style::StyleModifier, style::WidgetVisuals, vec2, Align2, Context, Id, InnerResponse,
NumExt as _, Painter, Popup, PopupCloseBehavior, Rect, Response, ScrollArea, Sense, Stroke,
TextStyle, TextWrapMode, Ui, UiBuilder, Vec2, WidgetInfo, WidgetText, WidgetType,
Align2, Context, Id, InnerResponse, NumExt as _, Painter, Popup, PopupCloseBehavior, Rect,
Response, ScrollArea, Sense, Stroke, TextStyle, TextWrapMode, Ui, UiBuilder, Vec2, WidgetInfo,
WidgetText, WidgetType, epaint, style::StyleModifier, style::WidgetVisuals, vec2,
};
#[expect(unused_imports)] // Documentation

View File

@@ -1,8 +1,8 @@
//! Frame container
use crate::{
epaint, layers::ShapeIdx, InnerResponse, Response, Sense, Style, Ui, UiBuilder, UiKind,
UiStackInfo,
InnerResponse, Response, Sense, Style, Ui, UiBuilder, UiKind, UiStackInfo, epaint,
layers::ShapeIdx,
};
use epaint::{Color32, CornerRadius, Margin, MarginF32, Rect, Shadow, Shape, Stroke};
@@ -143,7 +143,8 @@ pub struct Frame {
#[test]
fn frame_size() {
assert_eq!(
std::mem::size_of::<Frame>(), 32,
std::mem::size_of::<Frame>(),
32,
"Frame changed size! If it shrank - good! Update this test. If it grew - bad! Try to find a way to avoid it."
);
assert!(

View File

@@ -3,7 +3,7 @@ use crate::{
Button, Color32, Context, Frame, Id, InnerResponse, IntoAtoms, Layout, Popup,
PopupCloseBehavior, Response, Style, Ui, UiBuilder, UiKind, UiStack, UiStackInfo, Widget as _,
};
use emath::{vec2, Align, RectAlign, Vec2};
use emath::{Align, RectAlign, Vec2, vec2};
use epaint::Stroke;
/// Apply a menu style to the [`Style`].

View File

@@ -18,8 +18,8 @@
use emath::GuiRounding as _;
use crate::{
lerp, vec2, Align, Context, CursorIcon, Frame, Id, InnerResponse, LayerId, Layout, NumExt as _,
Rangef, Rect, Sense, Stroke, Ui, UiBuilder, UiKind, UiStackInfo, Vec2,
Align, Context, CursorIcon, Frame, Id, InnerResponse, LayerId, 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 {

View File

@@ -1,10 +1,10 @@
use crate::containers::menu::{menu_style, MenuConfig, MenuState};
use crate::containers::menu::{MenuConfig, MenuState, menu_style};
use crate::style::StyleModifier;
use crate::{
Area, AreaState, Context, Frame, Id, InnerResponse, Key, LayerId, Layout, Order, Response,
Sense, Ui, UiKind, UiStackInfo,
};
use emath::{vec2, Align, Pos2, Rect, RectAlign, Vec2};
use emath::{Align, Pos2, Rect, RectAlign, Vec2, vec2};
use std::iter::once;
/// What should we anchor the popup to?
@@ -573,10 +573,9 @@ impl<'a> Popup<'a> {
area = area.default_width(width);
}
let frame = frame.unwrap_or_else(|| Frame::popup(&ctx.style()));
let mut response = area.show(&ctx, |ui| {
style.apply(ui.style_mut());
let frame = frame.unwrap_or_else(|| Frame::popup(ui.style()));
frame.show(ui, content).inner
});

View File

@@ -1,6 +1,6 @@
use crate::{
pos2, vec2, Align2, Color32, Context, CursorIcon, Id, NumExt as _, Rect, Response, Sense,
Shape, Ui, UiBuilder, UiKind, UiStackInfo, Vec2, Vec2b,
Align2, Color32, Context, CursorIcon, Id, NumExt as _, Rect, Response, Sense, Shape, Ui,
UiBuilder, UiKind, UiStackInfo, Vec2, Vec2b, pos2, vec2,
};
#[derive(Clone, Copy, Debug)]

View File

@@ -3,8 +3,8 @@ use core::f32;
use emath::{GuiRounding as _, Pos2};
use crate::{
emath::TSTransform, InnerResponse, LayerId, PointerButton, Rangef, Rect, Response, Sense, Ui,
UiBuilder, Vec2,
InnerResponse, LayerId, PointerButton, Rangef, Rect, Response, Sense, Ui, UiBuilder, Vec2,
emath::TSTransform,
};
/// Creates a transformation that fits a given scene rectangle into the available screen size.

View File

@@ -3,8 +3,8 @@
use std::ops::{Add, AddAssign, BitOr, BitOrAssign};
use crate::{
emath, epaint, lerp, pass_state, pos2, remap, remap_clamp, Context, CursorIcon, Id,
NumExt as _, Pos2, Rangef, Rect, Sense, Ui, UiBuilder, UiKind, UiStackInfo, Vec2, Vec2b,
Context, CursorIcon, Id, NumExt as _, Pos2, Rangef, Rect, Sense, Ui, UiBuilder, UiKind,
UiStackInfo, Vec2, Vec2b, emath, epaint, lerp, pass_state, pos2, remap, remap_clamp,
};
#[derive(Clone, Copy, Debug)]

View File

@@ -9,7 +9,7 @@ use crate::collapsing_header::CollapsingState;
use crate::*;
use super::scroll_area::{ScrollBarVisibility, ScrollSource};
use super::{area, resize, Area, Frame, Resize, ScrollArea};
use super::{Area, Frame, Resize, ScrollArea, area, resize};
/// Builder for a floating window which can be dragged, closed, collapsed, resized and scrolled (off by default).
///

View File

@@ -4,16 +4,23 @@ use std::{borrow::Cow, cell::RefCell, panic::Location, sync::Arc, time::Duration
use emath::{GuiRounding as _, OrderedFloat};
use epaint::{
ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2, Rect, StrokeKind,
TessellationOptions, TextureAtlas, TextureId, Vec2,
emath::{self, TSTransform},
mutex::RwLock,
stats::PaintStats,
tessellator,
text::{FontInsert, FontPriority, Fonts},
vec2, ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2, Rect, StrokeKind,
TessellationOptions, TextureAtlas, TextureId, Vec2,
vec2,
};
use crate::{
Align2, CursorIcon, DeferredViewportUiCallback, FontDefinitions, Grid, Id, ImmediateViewport,
ImmediateViewportRendererCallback, Key, KeyboardShortcut, Label, LayerId, Memory,
ModifierNames, Modifiers, NumExt as _, Order, Painter, RawInput, Response, RichText,
ScrollArea, Sense, Style, TextStyle, TextureHandle, TextureOptions, Ui, ViewportBuilder,
ViewportCommand, ViewportId, ViewportIdMap, ViewportIdPair, ViewportIdSet, ViewportOutput,
Widget as _, WidgetRect, WidgetText,
animation_manager::AnimationManager,
containers::{self, area::AreaState},
data::output::PlatformOutput,
@@ -29,12 +36,6 @@ use crate::{
resize, response, scroll_area,
util::IdTypeMap,
viewport::ViewportClass,
Align2, CursorIcon, DeferredViewportUiCallback, FontDefinitions, Grid, Id, ImmediateViewport,
ImmediateViewportRendererCallback, Key, KeyboardShortcut, Label, LayerId, Memory,
ModifierNames, Modifiers, NumExt as _, Order, Painter, RawInput, Response, RichText,
ScrollArea, Sense, Style, TextStyle, TextureHandle, TextureOptions, Ui, ViewportBuilder,
ViewportCommand, ViewportId, ViewportIdMap, ViewportIdPair, ViewportIdSet, ViewportOutput,
Widget as _, WidgetRect, WidgetText,
};
#[cfg(feature = "accesskit")]
@@ -339,6 +340,15 @@ impl RepaintCause {
/// Per-viewport state related to repaint scheduling.
struct ViewportRepaintInfo {
/// Monotonically increasing counter.
///
/// Incremented at the end of [`Context::run`].
/// This can be smaller than [`Self::cumulative_pass_nr`],
/// but never larger.
cumulative_frame_nr: u64,
/// Monotonically increasing counter, counting the number of passes.
/// This can be larger than [`Self::cumulative_frame_nr`],
/// but never smaller.
cumulative_pass_nr: u64,
/// The duration which the backend will poll for new events
@@ -369,6 +379,7 @@ struct ViewportRepaintInfo {
impl Default for ViewportRepaintInfo {
fn default() -> Self {
Self {
cumulative_frame_nr: 0,
cumulative_pass_nr: 0,
// We haven't scheduled a repaint yet.
@@ -850,7 +861,10 @@ impl Context {
if max_passes <= output.platform_output.num_completed_passes {
#[cfg(feature = "log")]
log::debug!("Ignoring call request_discard, because max_passes={max_passes}. Requested from {:?}", output.platform_output.request_discard_reasons);
log::debug!(
"Ignoring call request_discard, because max_passes={max_passes}. Requested from {:?}",
output.platform_output.request_discard_reasons
);
break;
}
@@ -864,6 +878,7 @@ impl Context {
} else {
viewport.num_multipass_in_row = 0;
}
viewport.repaint.cumulative_frame_nr += 1;
});
output
@@ -1536,9 +1551,34 @@ impl Context {
}
}
/// The total number of completed frames.
///
/// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
///
/// This is always smaller or equal to [`Self::cumulative_pass_nr`].
pub fn cumulative_frame_nr(&self) -> u64 {
self.cumulative_frame_nr_for(self.viewport_id())
}
/// The total number of completed frames.
///
/// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
///
/// This is always smaller or equal to [`Self::cumulative_pass_nr_for`].
pub fn cumulative_frame_nr_for(&self, id: ViewportId) -> u64 {
self.read(|ctx| {
ctx.viewports
.get(&id)
.map_or(0, |v| v.repaint.cumulative_frame_nr)
})
}
/// 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).
///
/// If you instead want to know which pass index this is within the current frame,
/// use [`Self::current_pass_index`].
pub fn cumulative_pass_nr(&self) -> u64 {
self.cumulative_pass_nr_for(self.viewport_id())
}
@@ -1554,6 +1594,18 @@ impl Context {
})
}
/// The index of the current pass in the current frame, starting at zero.
///
/// Usually this is zero, but if something called [`Self::request_discard`] to do multi-pass layout,
/// then this will be incremented for each pass.
///
/// This just reads the value of [`PlatformOutput::num_completed_passes`].
///
/// To know the total number of passes ever completed, use [`Self::cumulative_pass_nr`].
pub fn current_pass_index(&self) -> usize {
self.output(|o| o.num_completed_passes)
}
/// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
///
/// If this is called at least once in a frame, then there will be another frame right after this.
@@ -1726,7 +1778,7 @@ impl Context {
/// This means the first pass will look glitchy, and ideally should not be shown to the user.
/// So [`crate::Grid`] calls [`Self::request_discard`] to cover up this glitches.
///
/// There is a limit to how many passes egui will perform, set by [`Options::max_passes`].
/// There is a limit to how many passes egui will perform, set by [`Options::max_passes`] (default=2).
/// Therefore, the request might be declined.
///
/// You can check if the current pass will be discarded with [`Self::will_discard`].
@@ -2305,7 +2357,9 @@ impl Context {
// If you see this message, it means we've been paying the cost of multi-pass for multiple frames in a row.
// This is likely a bug. `request_discard` should only be called in rare situations, when some layout changes.
let mut warning = format!("egui PERF WARNING: request_discard has been called {num_multipass_in_row} frames in a row");
let mut warning = format!(
"egui PERF WARNING: request_discard has been called {num_multipass_in_row} frames in a row"
);
self.viewport(|vp| {
for reason in &vp.output.request_discard_reasons {
warning += &format!("\n {reason}");
@@ -2983,36 +3037,54 @@ impl Context {
pub fn inspection_ui(&self, ui: &mut Ui) {
use crate::containers::CollapsingHeader;
ui.label(format!("Is using pointer: {}", self.is_using_pointer()))
.on_hover_text(
"Is egui currently using the pointer actively (e.g. dragging a slider)?",
);
ui.label(format!("Wants pointer input: {}", self.wants_pointer_input()))
.on_hover_text("Is egui currently interested in the location of the pointer (either because it is in use, or because it is hovering over a window).");
ui.label(format!(
"Wants keyboard input: {}",
self.wants_keyboard_input()
))
.on_hover_text("Is egui currently listening for text input?");
ui.label(format!(
"Keyboard focus widget: {}",
self.memory(|m| m.focused())
.as_ref()
.map(Id::short_debug_format)
.unwrap_or_default()
))
.on_hover_text("Is egui currently listening for text input?");
crate::Grid::new("egui-inspection-grid")
.num_columns(2)
.striped(true)
.show(ui, |ui| {
ui.label("Total ui frames:");
ui.monospace(ui.ctx().cumulative_frame_nr().to_string());
ui.end_row();
let pointer_pos = self
.pointer_hover_pos()
.map_or_else(String::new, |pos| format!("{pos:?}"));
ui.label(format!("Pointer pos: {pointer_pos}"));
ui.label("Total ui passes:");
ui.monospace(ui.ctx().cumulative_pass_nr().to_string());
ui.end_row();
let top_layer = self
.pointer_hover_pos()
.and_then(|pos| self.layer_id_at(pos))
.map_or_else(String::new, |layer| layer.short_debug_format());
ui.label(format!("Top layer under mouse: {top_layer}"));
ui.label("Is using pointer")
.on_hover_text("Is egui currently using the pointer actively (e.g. dragging a slider)?");
ui.monospace(self.is_using_pointer().to_string());
ui.end_row();
ui.label("Wants pointer input")
.on_hover_text("Is egui currently interested in the location of the pointer (either because it is in use, or because it is hovering over a window).");
ui.monospace(self.wants_pointer_input().to_string());
ui.end_row();
ui.label("Wants keyboard input").on_hover_text("Is egui currently listening for text input?");
ui.monospace(self.wants_keyboard_input().to_string());
ui.end_row();
ui.label("Keyboard focus widget").on_hover_text("Is egui currently listening for text input?");
ui.monospace(self.memory(|m| m.focused())
.as_ref()
.map(Id::short_debug_format)
.unwrap_or_default());
ui.end_row();
let pointer_pos = self
.pointer_hover_pos()
.map_or_else(String::new, |pos| format!("{pos:?}"));
ui.label("Pointer pos");
ui.monospace(pointer_pos);
ui.end_row();
let top_layer = self
.pointer_hover_pos()
.and_then(|pos| self.layer_id_at(pos))
.map_or_else(String::new, |layer| layer.short_debug_format());
ui.label("Top layer under mouse");
ui.monospace(top_layer);
ui.end_row();
});
ui.add_space(16.0);
@@ -3446,6 +3518,7 @@ impl Context {
/// Release all memory and textures related to the given image URI.
///
/// If you attempt to load the image again, it will be reloaded from scratch.
/// Also this cancels any ongoing loading of the image.
pub fn forget_image(&self, uri: &str) {
use load::BytesLoader as _;

View File

@@ -3,8 +3,8 @@
use epaint::ColorImage;
use crate::{
emath::{Pos2, Rect, Vec2},
Key, Theme, ViewportId, ViewportIdMap,
emath::{Pos2, Rect, Vec2},
};
/// What the integrations provides to egui at the start of each frame.

View File

@@ -6,7 +6,7 @@
//! to get callbacks on certain events ([`Context::on_begin_pass`], [`Context::on_end_pass`]).
use crate::{
text, Align, Align2, Color32, Context, FontFamily, FontId, Id, Rect, Shape, Vec2, WidgetText,
Align, Align2, Color32, Context, FontFamily, FontId, Id, Rect, Shape, Vec2, WidgetText, text,
};
/// Register this plugin on the given egui context,

View File

@@ -1,8 +1,8 @@
use emath::GuiRounding as _;
use crate::{
vec2, Align2, Color32, Context, Id, InnerResponse, NumExt as _, Painter, Rect, Region, Style,
Ui, UiBuilder, Vec2,
Align2, Color32, Context, Id, InnerResponse, NumExt as _, Painter, Rect, Region, Style, Ui,
UiBuilder, Vec2, vec2,
};
#[cfg(debug_assertions)]

View File

@@ -2,7 +2,7 @@ use ahash::HashMap;
use emath::TSTransform;
use crate::{ahash, emath, id::IdSet, LayerId, Pos2, Rect, Sense, WidgetRect, WidgetRects};
use crate::{LayerId, Pos2, Rect, Sense, WidgetRect, WidgetRects, ahash, emath, id::IdSet};
/// Result of a hit-test against [`WidgetRects`].
///
@@ -466,7 +466,7 @@ fn should_prioritize_hits_on_back(back: Rect, front: Rect) -> bool {
#[cfg(test)]
mod tests {
use emath::{pos2, vec2, Rect};
use emath::{Rect, pos2, vec2};
use crate::{Id, Sense};

View File

@@ -1,11 +1,11 @@
mod touch_state;
use crate::data::input::{
Event, EventFilter, KeyboardShortcut, Modifiers, MouseWheelUnit, PointerButton, RawInput,
TouchDeviceId, ViewportInfo, NUM_POINTER_BUTTONS,
Event, EventFilter, KeyboardShortcut, Modifiers, MouseWheelUnit, NUM_POINTER_BUTTONS,
PointerButton, RawInput, TouchDeviceId, ViewportInfo,
};
use crate::{
emath::{vec2, NumExt as _, Pos2, Rect, Vec2},
emath::{NumExt as _, Pos2, Rect, Vec2, vec2},
util::History,
};
use std::{

View File

@@ -1,9 +1,9 @@
use std::{collections::BTreeMap, fmt::Debug};
use crate::{
data::input::TouchDeviceId,
emath::{normalized_angle, Pos2, Vec2},
Event, RawInput, TouchId, TouchPhase,
data::input::TouchDeviceId,
emath::{Pos2, Vec2, normalized_angle},
};
/// All you probably need to know about a multi-touch gesture.
@@ -174,7 +174,7 @@ impl TouchState {
if added_or_removed_touches {
// Adding or removing fingers makes the average values "jump". We better forget
// about the previous values, and don't create delta information for this frame:
if let Some(ref mut state) = &mut self.gesture_state {
if let Some(state) = &mut self.gesture_state {
state.previous = None;
}
}
@@ -224,7 +224,7 @@ impl TouchState {
fn update_gesture(&mut self, time: f64, pointer_pos: Option<Pos2>) {
if let Some(dyn_state) = self.calc_dynamic_state() {
if let Some(ref mut state) = &mut self.gesture_state {
if let Some(state) = &mut self.gesture_state {
// updating an ongoing gesture
state.previous = Some(state.current);
state.current = dyn_state;

View File

@@ -1,6 +1,6 @@
//! How mouse and touch interzcts with widgets.
use crate::{hit_test, id, input_state, memory, Id, InputState, Key, WidgetRects};
use crate::{Id, InputState, Key, WidgetRects, hit_test, id, input_state, memory};
use self::{hit_test::WidgetHits, id::IdSet, input_state::PointerEvent, memory::InteractionState};

View File

@@ -1,7 +1,7 @@
//! Showing UI:s for egui/epaint types.
use crate::{
epaint, memory, pos2, remap_clamp, vec2, Color32, CursorIcon, FontFamily, FontId, Label, Mesh,
NumExt as _, Rect, Response, Sense, Shape, Slider, TextStyle, TextWrapMode, Ui, Widget,
Color32, CursorIcon, FontFamily, FontId, Label, Mesh, NumExt as _, Rect, Response, Sense,
Shape, Slider, TextStyle, TextWrapMode, Ui, Widget, epaint, memory, pos2, remap_clamp, vec2,
};
pub fn font_family_ui(ui: &mut Ui, font_family: &mut FontFamily) {

View File

@@ -1,8 +1,8 @@
//! Handles paint layers, i.e. how things
//! are sometimes painted behind or in front of other things.
use crate::{ahash, epaint, Id, IdMap, Rect};
use epaint::{emath::TSTransform, ClippedShape, Shape};
use crate::{Id, IdMap, Rect, ahash, epaint};
use epaint::{ClippedShape, Shape, emath::TSTransform};
/// Different layer categories
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]

View File

@@ -1,8 +1,8 @@
use emath::GuiRounding as _;
use crate::{
emath::{pos2, vec2, Align2, NumExt as _, Pos2, Rect, Vec2},
Align,
emath::{Align2, NumExt as _, Pos2, Rect, Vec2, pos2, vec2},
};
const INFINITY: f32 = f32::INFINITY;

View File

@@ -3,7 +3,7 @@
//! Try the live web demo: <https://www.egui.rs/#demo>. Read more about egui at <https://github.com/emilk/egui>.
//!
//! `egui` is in heavy development, with each new version having breaking changes.
//! You need to have rust 1.84.0 or later to use `egui`.
//! You need to have rust 1.85.0 or later to use `egui`.
//!
//! To quickly get started with egui, you can take a look at [`eframe_template`](https://github.com/emilk/eframe_template)
//! which uses [`eframe`](https://docs.rs/eframe).
@@ -463,22 +463,21 @@ pub use epaint::emath;
pub use ecolor::hex_color;
pub use ecolor::{Color32, Rgba};
pub use emath::{
lerp, pos2, remap, remap_clamp, vec2, Align, Align2, NumExt, Pos2, Rangef, Rect, RectAlign,
Vec2, Vec2b,
Align, Align2, NumExt, Pos2, Rangef, Rect, RectAlign, Vec2, Vec2b, lerp, pos2, remap,
remap_clamp, vec2,
};
pub use epaint::{
mutex,
ClippedPrimitive, ColorImage, CornerRadius, FontImage, ImageData, Margin, Mesh, PaintCallback,
PaintCallbackInfo, Shadow, Shape, Stroke, StrokeKind, TextureHandle, TextureId, mutex,
text::{FontData, FontDefinitions, FontFamily, FontId, FontTweak},
textures::{TextureFilter, TextureOptions, TextureWrapMode, TexturesDelta},
ClippedPrimitive, ColorImage, CornerRadius, FontImage, ImageData, Margin, Mesh, PaintCallback,
PaintCallbackInfo, Shadow, Shape, Stroke, StrokeKind, TextureHandle, TextureId,
};
pub mod text {
pub use crate::text_selection::CCursorRange;
pub use epaint::text::{
cursor::CCursor, FontData, FontDefinitions, FontFamily, Fonts, Galley, LayoutJob,
LayoutSection, TextFormat, TextWrapping, TAB_SIZE,
FontData, FontDefinitions, FontFamily, Fonts, Galley, LayoutJob, LayoutSection, TAB_SIZE,
TextFormat, TextWrapping, cursor::CCursor,
};
}
@@ -487,12 +486,12 @@ pub use self::{
containers::*,
context::{Context, RepaintCause, RequestRepaintInfo},
data::{
Key, UserData,
input::*,
output::{
self, CursorIcon, FullOutput, OpenUrl, OutputCommand, PlatformOutput,
UserAttentionType, WidgetInfo,
},
Key, UserData,
},
drag_and_drop::DragAndDrop,
epaint::text::TextWrapMode,

View File

@@ -65,7 +65,7 @@ use std::{
use ahash::HashMap;
use emath::{Float as _, OrderedFloat};
use epaint::{mutex::Mutex, textures::TextureOptions, ColorImage, TextureHandle, TextureId, Vec2};
use epaint::{ColorImage, TextureHandle, TextureId, Vec2, mutex::Mutex, textures::TextureOptions};
use crate::Context;

View File

@@ -1,6 +1,6 @@
use super::{
generate_loader_id, Bytes, BytesLoadResult, BytesLoader, BytesPoll, Context, Cow, HashMap,
LoadError, Mutex,
Bytes, BytesLoadResult, BytesLoader, BytesPoll, Context, Cow, HashMap, LoadError, Mutex,
generate_loader_id,
};
/// Maps URI:s to [`Bytes`], e.g. found with `include_bytes!`.

View File

@@ -6,8 +6,8 @@ use ahash::{HashMap, HashSet};
use epaint::emath::TSTransform;
use crate::{
area, vec2, EventFilter, Id, IdMap, LayerId, Order, Pos2, Rangef, RawInput, Rect, Style, Vec2,
ViewportId, ViewportIdMap, ViewportIdSet,
EventFilter, Id, IdMap, LayerId, Order, Pos2, Rangef, RawInput, Rect, Style, Vec2, ViewportId,
ViewportIdMap, ViewportIdSet, area, vec2,
};
mod theme;
@@ -377,8 +377,8 @@ impl Options {
reduce_texture_memory,
} = self;
use crate::containers::CollapsingHeader;
use crate::Widget as _;
use crate::containers::CollapsingHeader;
CollapsingHeader::new("⚙ Options")
.default_open(false)
@@ -1250,8 +1250,11 @@ impl Areas {
///
/// The two layers must have the same [`LayerId::order`].
pub fn set_sublayer(&mut self, parent: LayerId, child: LayerId) {
debug_assert_eq!(parent.order, child.order,
"DEBUG ASSERT: Trying to set sublayers across layers of different order ({:?}, {:?}), which is currently undefined behavior in egui", parent.order, child.order);
debug_assert_eq!(
parent.order, child.order,
"DEBUG ASSERT: Trying to set sublayers across layers of different order ({:?}, {:?}), which is currently undefined behavior in egui",
parent.order, child.order
);
self.sublayers.entry(parent).or_default().insert(child);

View File

@@ -30,11 +30,7 @@ impl Theme {
/// Chooses between [`Self::Dark`] or [`Self::Light`] based on a boolean value.
pub fn from_dark_mode(dark_mode: bool) -> Self {
if dark_mode {
Self::Dark
} else {
Self::Light
}
if dark_mode { Self::Dark } else { Self::Light }
}
}

View File

@@ -17,14 +17,13 @@
//! ```
use super::{
style::WidgetVisuals, Align, Context, Id, InnerResponse, PointerState, Pos2, Rect, Response,
Sense, TextStyle, Ui, Vec2,
Align, Context, Id, InnerResponse, PointerState, Pos2, Rect, Response, Sense, TextStyle, Ui,
Vec2, style::WidgetVisuals,
};
use crate::{
epaint, vec2,
widgets::{Button, ImageButton},
Align2, Area, Color32, Frame, Key, LayerId, Layout, NumExt as _, Order, Stroke, Style,
TextWrapMode, UiKind, WidgetText,
TextWrapMode, UiKind, WidgetText, epaint, vec2,
widgets::{Button, ImageButton},
};
use epaint::mutex::RwLock;
use std::sync::Arc;

View File

@@ -71,7 +71,8 @@ impl OperatingSystem {
#[cfg(feature = "log")]
log::warn!(
"egui: Failed to guess operating system from User-Agent {:?}. Please file an issue at https://github.com/emilk/egui/issues",
user_agent);
user_agent
);
Self::Unknown
}

View File

@@ -2,14 +2,14 @@ use std::sync::Arc;
use emath::GuiRounding as _;
use epaint::{
text::{Fonts, Galley, LayoutJob},
CircleShape, ClippedShape, CornerRadius, PathStroke, RectShape, Shape, Stroke, StrokeKind,
text::{Fonts, Galley, LayoutJob},
};
use crate::{
Color32, Context, FontId,
emath::{Align2, Pos2, Rangef, Rect, Vec2},
layers::{LayerId, PaintList, ShapeIdx},
Color32, Context, FontId,
};
/// Helper to paint shapes and text to a specific region on a specific layer.

View File

@@ -1,9 +1,9 @@
use ahash::HashMap;
use crate::{id::IdSet, style, Align, Id, IdMap, LayerId, Rangef, Rect, Vec2, WidgetRects};
use crate::{Align, Id, IdMap, LayerId, Rangef, Rect, Vec2, WidgetRects, id::IdSet, style};
#[cfg(debug_assertions)]
use crate::{pos2, Align2, Color32, FontId, NumExt as _, Painter};
use crate::{Align2, Color32, FontId, NumExt as _, Painter, pos2};
/// Reset at the start of each frame.
#[derive(Clone, Debug, Default)]

View File

@@ -1,4 +1,4 @@
use crate::{grid, vec2, Layout, Painter, Pos2, Rect, Region, Vec2};
use crate::{Layout, Painter, Pos2, Rect, Region, Vec2, grid, vec2};
#[cfg(debug_assertions)]
use crate::{Align2, Color32, Stroke};

View File

@@ -1,9 +1,10 @@
use std::{any::Any, sync::Arc};
use crate::{
Context, CursorIcon, Id, LayerId, PointerButton, Popup, PopupKind, Sense, Tooltip, Ui,
WidgetRect, WidgetText,
emath::{Align, Pos2, Rect, Vec2},
pass_state, Context, CursorIcon, Id, LayerId, PointerButton, Popup, PopupKind, Sense, Tooltip,
Ui, WidgetRect, WidgetText,
pass_state,
};
// ----------------------------------------------------------------------------

View File

@@ -3,14 +3,14 @@
#![allow(clippy::if_same_then_else)]
use emath::Align;
use epaint::{text::FontTweak, CornerRadius, Shadow, Stroke};
use epaint::{CornerRadius, Shadow, Stroke, text::FontTweak};
use std::{collections::BTreeMap, ops::RangeInclusive, sync::Arc};
use crate::{
ecolor::Color32,
emath::{pos2, vec2, Rangef, Rect, Vec2},
ComboBox, CursorIcon, FontFamily, FontId, Grid, Margin, Response, RichText, TextWrapMode,
WidgetText,
ecolor::Color32,
emath::{Rangef, Rect, Vec2, pos2, vec2},
};
/// How to format numbers in e.g. a [`crate::DragValue`].
@@ -1576,8 +1576,8 @@ impl Default for Widgets {
// ----------------------------------------------------------------------------
use crate::{
widgets::{reset_button, DragValue, Slider, Widget},
Ui,
widgets::{DragValue, Slider, Widget, reset_button},
};
impl Style {

View File

@@ -2,7 +2,7 @@ use emath::TSTransform;
use crate::{Context, Galley, Id};
use super::{text_cursor_state::is_word_char, CCursorRange};
use super::{CCursorRange, text_cursor_state::is_word_char};
/// Update accesskit with the current text state.
pub fn update_accesskit_for_text_widget(

View File

@@ -1,6 +1,6 @@
use epaint::{text::cursor::CCursor, Galley};
use epaint::{Galley, text::cursor::CCursor};
use crate::{os::OperatingSystem, Event, Id, Key, Modifiers};
use crate::{Event, Id, Key, Modifiers, os::OperatingSystem};
use super::text_cursor_state::{ccursor_next_word, ccursor_previous_word, slice_char_range};

View File

@@ -3,14 +3,14 @@ use std::sync::Arc;
use emath::TSTransform;
use crate::{
layers::ShapeIdx, text::CCursor, text_selection::CCursorRange, Context, CursorIcon, Event,
Galley, Id, LayerId, Pos2, Rect, Response, Ui,
Context, CursorIcon, Event, Galley, Id, LayerId, Pos2, Rect, Response, Ui, layers::ShapeIdx,
text::CCursor, text_selection::CCursorRange,
};
use super::{
text_cursor_state::cursor_rect,
visuals::{paint_text_selection, RowVertexIndices},
TextCursorState,
text_cursor_state::cursor_rect,
visuals::{RowVertexIndices, paint_text_selection},
};
/// Turn on to help debug this

View File

@@ -1,9 +1,9 @@
//! Text cursor changes/interaction, without modifying the text.
use epaint::text::{cursor::CCursor, Galley};
use epaint::text::{Galley, cursor::CCursor};
use unicode_segmentation::UnicodeSegmentation as _;
use crate::{epaint, NumExt as _, Rect, Response, Ui};
use crate::{NumExt as _, Rect, Response, Ui, epaint};
use super::CCursorRange;

View File

@@ -1,6 +1,6 @@
use std::sync::Arc;
use crate::{pos2, vec2, Galley, Painter, Rect, Ui, Visuals};
use crate::{Galley, Painter, Rect, Ui, Visuals, pos2, vec2};
use super::CCursorRange;

View File

@@ -5,11 +5,15 @@ use emath::GuiRounding as _;
use epaint::mutex::RwLock;
use std::{any::Any, hash::Hash, sync::Arc};
use crate::close_tag::ClosableTag;
use crate::containers::menu;
#[cfg(debug_assertions)]
use crate::Stroke;
use crate::close_tag::ClosableTag;
use crate::containers::menu;
use crate::{
Align, Color32, Context, CursorIcon, DragAndDrop, Id, InnerResponse, InputState, IntoAtoms,
LayerId, Memory, Order, Painter, PlatformOutput, Pos2, Rangef, Rect, Response, Rgba, RichText,
Sense, Style, TextStyle, TextWrapMode, UiBuilder, UiKind, UiStack, UiStackInfo, Vec2,
WidgetRect, WidgetText,
containers::{CollapsingHeader, CollapsingResponse, Frame},
ecolor::Hsva,
emath, epaint,
@@ -22,13 +26,9 @@ use crate::{
util::IdTypeMap,
vec2, widgets,
widgets::{
color_picker, Button, Checkbox, DragValue, Hyperlink, Image, ImageSource, Label, Link,
RadioButton, SelectableLabel, Separator, Spinner, TextEdit, Widget,
Button, Checkbox, DragValue, Hyperlink, Image, ImageSource, Label, Link, RadioButton,
SelectableLabel, Separator, Spinner, TextEdit, Widget, color_picker,
},
Align, Color32, Context, CursorIcon, DragAndDrop, Id, InnerResponse, InputState, IntoAtoms,
LayerId, Memory, Order, Painter, PlatformOutput, Pos2, Rangef, Rect, Response, Rgba, RichText,
Sense, Style, TextStyle, TextWrapMode, UiBuilder, UiKind, UiStack, UiStackInfo, Vec2,
WidgetRect, WidgetText,
};
// ----------------------------------------------------------------------------

View File

@@ -1,8 +1,8 @@
use std::{hash::Hash, sync::Arc};
use crate::close_tag::ClosableTag;
#[expect(unused_imports)] // Used for doclinks
use crate::Ui;
use crate::close_tag::ClosableTag;
use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo};
/// Build a [`Ui`] as the child of another [`Ui`].

View File

@@ -4,8 +4,8 @@ use std::fmt::Formatter;
use std::{borrow::Cow, sync::Arc};
use crate::{
text::{LayoutJob, TextWrapping},
Align, Color32, FontFamily, FontSelection, Galley, Style, TextStyle, TextWrapMode, Ui, Visuals,
text::{LayoutJob, TextWrapping},
};
/// Text and optional style choices for it.

View File

@@ -1,6 +1,6 @@
use crate::{
epaint, pos2, Atom, AtomLayout, Atoms, Id, IntoAtoms, NumExt as _, Response, Sense, Shape, Ui,
Vec2, Widget, WidgetInfo, WidgetType,
Atom, AtomLayout, Atoms, Id, IntoAtoms, NumExt as _, Response, Sense, Shape, Ui, Vec2, Widget,
WidgetInfo, WidgetType, epaint, pos2,
};
// TODO(emilk): allow checkbox without a text label

View File

@@ -2,12 +2,13 @@
use crate::util::fixed_cache::FixedCache;
use crate::{
epaint, lerp, remap_clamp, Area, Context, DragValue, Frame, Id, Key, Order, Painter, Response,
Sense, Ui, UiKind, Widget as _, WidgetInfo, WidgetType,
Context, DragValue, Id, Painter, Popup, PopupCloseBehavior, Response, Sense, Ui, Widget as _,
WidgetInfo, WidgetType, epaint, lerp, remap_clamp,
};
use epaint::{
Mesh, Rect, Shape, Stroke, StrokeKind, Vec2,
ecolor::{Color32, Hsva, HsvaGamma, Rgba},
pos2, vec2, Mesh, Rect, Shape, Stroke, StrokeKind, Vec2,
pos2, vec2,
};
fn contrast_color(color: impl Into<Rgba>) -> Color32 {
@@ -496,35 +497,17 @@ pub fn color_edit_button_hsva(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> Res
button_response = button_response.on_hover_text("Click to edit color");
}
if button_response.clicked() {
ui.memory_mut(|mem| mem.toggle_popup(popup_id));
}
const COLOR_SLIDER_WIDTH: f32 = 275.0;
// TODO(lucasmerlin): Update this to use new Popup struct
if ui.memory(|mem| mem.is_popup_open(popup_id)) {
ui.memory_mut(|mem| mem.keep_popup_open(popup_id));
let area_response = Area::new(popup_id)
.kind(UiKind::Picker)
.order(Order::Foreground)
.fixed_pos(button_response.rect.max)
.show(ui.ctx(), |ui| {
ui.spacing_mut().slider_width = COLOR_SLIDER_WIDTH;
Frame::popup(ui.style()).show(ui, |ui| {
if color_picker_hsva_2d(ui, hsva, alpha) {
button_response.mark_changed();
}
});
})
.response;
if !button_response.clicked()
&& (ui.input(|i| i.key_pressed(Key::Escape)) || area_response.clicked_elsewhere())
{
ui.memory_mut(|mem| mem.close_popup(popup_id));
}
}
Popup::menu(&button_response)
.id(popup_id)
.close_behavior(PopupCloseBehavior::CloseOnClickOutside)
.show(|ui| {
ui.spacing_mut().slider_width = COLOR_SLIDER_WIDTH;
if color_picker_hsva_2d(ui, hsva, alpha) {
button_response.mark_changed();
}
});
button_response
}

View File

@@ -3,8 +3,8 @@
use std::{cmp::Ordering, ops::RangeInclusive};
use crate::{
emath, text, Button, CursorIcon, Id, Key, Modifiers, NumExt as _, Response, RichText, Sense,
TextEdit, TextWrapMode, Ui, Widget, WidgetInfo, MINUS_CHAR_STR,
Button, CursorIcon, Id, Key, MINUS_CHAR_STR, Modifiers, NumExt as _, Response, RichText, Sense,
TextEdit, TextWrapMode, Ui, Widget, WidgetInfo, emath, text,
};
// ----------------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
use crate::{
epaint, text_selection, CursorIcon, Label, Response, Sense, Stroke, Ui, Widget, WidgetInfo,
WidgetText, WidgetType,
CursorIcon, Label, Response, Sense, Stroke, Ui, Widget, WidgetInfo, WidgetText, WidgetType,
epaint, text_selection,
};
use self::text_selection::LabelSelectionState;

View File

@@ -2,14 +2,15 @@ use std::{borrow::Cow, slice::Iter, sync::Arc, time::Duration};
use emath::{Align, Float as _, GuiRounding as _, NumExt as _, Rot2};
use epaint::{
text::{LayoutJob, TextFormat, TextWrapping},
RectShape,
text::{LayoutJob, TextFormat, TextWrapping},
};
use crate::{
load::{Bytes, SizeHint, SizedTexture, TextureLoadResult, TexturePoll},
pos2, Color32, Context, CornerRadius, Id, Mesh, Painter, Rect, Response, Sense, Shape, Spinner,
Color32, Context, CornerRadius, Id, Mesh, Painter, Rect, Response, Sense, Shape, Spinner,
TextStyle, TextureOptions, Ui, Vec2, Widget, WidgetInfo, WidgetType,
load::{Bytes, SizeHint, SizedTexture, TextureLoadResult, TexturePoll},
pos2,
};
/// A widget which displays an image.
@@ -499,7 +500,7 @@ impl ImageSize {
let point_size = match fit {
ImageFit::Original { scale } => {
return SizeHint::Scale((pixels_per_point * scale).ord())
return SizeHint::Scale((pixels_per_point * scale).ord());
}
ImageFit::Fraction(fract) => available_size * fract,
ImageFit::Exact(size) => size,

View File

@@ -1,6 +1,6 @@
use crate::{
widgets, Color32, CornerRadius, Image, Rect, Response, Sense, Ui, Vec2, Widget, WidgetInfo,
WidgetType,
Color32, CornerRadius, Image, Rect, Response, Sense, Ui, Vec2, Widget, WidgetInfo, WidgetType,
widgets,
};
/// A clickable image within a frame.

View File

@@ -1,8 +1,8 @@
use std::sync::Arc;
use crate::{
epaint, pos2, text_selection::LabelSelectionState, Align, Direction, FontSelection, Galley,
Pos2, Response, Sense, Stroke, TextWrapMode, Ui, Widget, WidgetInfo, WidgetText, WidgetType,
Align, Direction, FontSelection, Galley, Pos2, Response, Sense, Stroke, TextWrapMode, Ui,
Widget, WidgetInfo, WidgetText, WidgetType, epaint, pos2, text_selection::LabelSelectionState,
};
/// Static text.

View File

@@ -4,7 +4,7 @@
//! * `ui.add(Label::new("Text").text_color(color::red));`
//! * `if ui.add(Button::new("Click me")).clicked() { … }`
use crate::{epaint, Response, Ui};
use crate::{Response, Ui, epaint};
mod button;
mod checkbox;
@@ -28,8 +28,8 @@ pub use self::{
drag_value::DragValue,
hyperlink::{Hyperlink, Link},
image::{
decode_animated_image_uri, has_gif_magic_header, has_webp_header, paint_texture_at,
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,

View File

@@ -1,6 +1,6 @@
use crate::{
lerp, vec2, Color32, CornerRadius, NumExt as _, Pos2, Rect, Response, Rgba, Sense, Shape,
Stroke, TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetType,
Color32, CornerRadius, NumExt as _, Pos2, Rect, Response, Rgba, Sense, Shape, Stroke,
TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetType, lerp, vec2,
};
enum ProgressBarText {

View File

@@ -1,6 +1,6 @@
use crate::{
epaint, Atom, AtomLayout, Atoms, Id, IntoAtoms, NumExt as _, Response, Sense, Ui, Vec2, Widget,
WidgetInfo, WidgetType,
Atom, AtomLayout, Atoms, Id, IntoAtoms, NumExt as _, Response, Sense, Ui, Vec2, Widget,
WidgetInfo, WidgetType, epaint,
};
/// One out of several alternatives, either selected or not.

View File

@@ -1,4 +1,4 @@
use crate::{vec2, Response, Sense, Ui, Vec2, Widget};
use crate::{Response, Sense, Ui, Vec2, Widget, vec2};
/// A visual separator. A horizontal or vertical line (depending on [`crate::Layout`]).
///

View File

@@ -3,9 +3,9 @@
use std::ops::RangeInclusive;
use crate::{
emath, epaint, lerp, pos2, remap, remap_clamp, style, style::HandleShape, vec2, Color32,
DragValue, EventFilter, Key, Label, NumExt as _, Pos2, Rangef, Rect, Response, Sense,
TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, MINUS_CHAR_STR,
Color32, DragValue, EventFilter, Key, Label, MINUS_CHAR_STR, NumExt as _, Pos2, Rangef, Rect,
Response, Sense, TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, emath,
epaint, lerp, pos2, remap, remap_clamp, style, style::HandleShape, vec2,
};
use super::drag_value::clamp_value_to_range;
@@ -134,11 +134,7 @@ impl<'a> Slider<'a> {
value.to_f64()
});
if Num::INTEGRAL {
slf.integer()
} else {
slf
}
if Num::INTEGRAL { slf.integer() } else { slf }
}
pub fn from_get_set(
@@ -736,7 +732,7 @@ impl Slider<'_> {
let prev_value = self.get_value();
let prev_position = self.position_from_value(prev_value, position_range);
let new_position = prev_position + ui_point_per_step * kb_step;
let new_value = match self.step {
let mut new_value = match self.step {
Some(step) => prev_value + (kb_step as f64 * step),
None if self.smart_aim => {
let aim_radius = 0.49 * ui_point_per_step; // Chosen so we don't include `prev_value` in the search.
@@ -747,6 +743,19 @@ impl Slider<'_> {
}
_ => self.value_from_position(new_position, position_range),
};
if let Some(max_decimals) = self.max_decimals {
// self.set_value rounds, so ensure we reach at the least the next breakpoint
// note: we give it a little bit of leeway due to floating point errors. (0.1 isn't representable in binary)
// 'set_value' will round it to the nearest value.
let min_increment = 1.0 / (10.0_f64.powi(max_decimals as i32));
new_value = if new_value > prev_value {
f64::max(new_value, prev_value + min_increment * 1.001)
} else if new_value < prev_value {
f64::min(new_value, prev_value - min_increment * 1.001)
} else {
new_value
};
}
self.set_value(new_value);
}

View File

@@ -1,4 +1,4 @@
use epaint::{emath::lerp, vec2, Color32, Pos2, Rect, Shape, Stroke};
use epaint::{Color32, Pos2, Rect, Shape, Stroke, emath::lerp, vec2};
use crate::{Response, Sense, Ui, Widget, WidgetInfo, WidgetType};

View File

@@ -2,19 +2,19 @@ use std::sync::Arc;
use emath::{Rect, TSTransform};
use epaint::{
text::{cursor::CCursor, Galley, LayoutJob},
StrokeKind,
text::{Galley, LayoutJob, cursor::CCursor},
};
use crate::{
epaint,
Align, Align2, Color32, Context, CursorIcon, Event, EventFilter, FontSelection, Id, ImeEvent,
Key, KeyboardShortcut, Margin, Modifiers, NumExt as _, Response, Sense, Shape, TextBuffer,
TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetWithState, epaint,
os::OperatingSystem,
output::OutputEvent,
response, text_selection,
text_selection::{text_cursor_state::cursor_rect, visuals::paint_text_selection, CCursorRange},
vec2, Align, Align2, Color32, Context, CursorIcon, Event, EventFilter, FontSelection, Id,
ImeEvent, Key, KeyboardShortcut, Margin, Modifiers, NumExt as _, Response, Sense, Shape,
TextBuffer, TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetWithState,
text_selection::{CCursorRange, text_cursor_state::cursor_rect, visuals::paint_text_selection},
vec2,
};
use super::{TextEditOutput, TextEditState};

View File

@@ -3,8 +3,8 @@ use std::sync::Arc;
use crate::mutex::Mutex;
use crate::{
text_selection::{CCursorRange, TextCursorState},
Context, Id,
text_selection::{CCursorRange, TextCursorState},
};
pub type TextEditUndoer = crate::util::undoer::Undoer<(CCursorRange, String)>;

View File

@@ -1,8 +1,8 @@
use std::{borrow::Cow, ops::Range};
use epaint::{
text::{cursor::CCursor, TAB_SIZE},
Galley,
text::{TAB_SIZE, cursor::CCursor},
};
use crate::{

View File

@@ -1,8 +1,8 @@
use egui::{
Color32, Painter, Pos2, Rect, Shape, Stroke, Ui, Vec2,
containers::{CollapsingHeader, Frame},
emath, pos2,
widgets::Slider,
Color32, Painter, Pos2, Rect, Shape, Stroke, Ui, Vec2,
};
use std::f32::consts::TAU;

View File

@@ -1,9 +1,9 @@
use egui::emath::Rot2;
use egui::panel::Side;
use egui::panel::TopBottomSide;
use egui::ImageFit;
use egui::Slider;
use egui::Vec2;
use egui::emath::Rot2;
use egui::panel::Side;
use egui::panel::TopBottomSide;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ImageViewer {

View File

@@ -146,6 +146,10 @@ impl BackendPanel {
// builds to keep the noise down in the official demo.
if cfg!(debug_assertions) {
ui.collapsing("More…", |ui| {
ui.horizontal(|ui| {
ui.label("Total ui frames:");
ui.monospace(ui.ctx().cumulative_frame_nr().to_string());
});
ui.horizontal(|ui| {
ui.label("Total ui passes:");
ui.monospace(ui.ctx().cumulative_pass_nr().to_string());

View File

@@ -53,7 +53,7 @@ impl FrameHistory {
}
fn graph(&self, ui: &mut egui::Ui) -> egui::Response {
use egui::{emath, epaint, pos2, vec2, Pos2, Rect, Sense, Shape, Stroke, TextStyle};
use egui::{Pos2, Rect, Sense, Shape, Stroke, TextStyle, emath, epaint, pos2, vec2};
ui.label("egui CPU usage history");

View File

@@ -16,7 +16,9 @@ fn main() -> eframe::Result {
start_puffin_server();
#[cfg(not(feature = "puffin"))]
panic!("Unknown argument: {arg} - you need to enable the 'puffin' feature to use this.");
panic!(
"Unknown argument: {arg} - you need to enable the 'puffin' feature to use this."
);
}
_ => {
@@ -39,7 +41,12 @@ fn main() -> eframe::Result {
rust_log += &format!(",{loud_crate}=warn");
}
}
std::env::set_var("RUST_LOG", rust_log);
// SAFETY: we call this from the main thread without any other threads running.
#[expect(unsafe_code)]
unsafe {
std::env::set_var("RUST_LOG", rust_log);
}
}
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).

View File

@@ -1,8 +1,8 @@
use egui::accesskit::Role;
use egui::Vec2;
use egui::accesskit::Role;
use egui_demo_app::{Anchor, WrapApp};
use egui_kittest::kittest::Queryable as _;
use egui_kittest::SnapshotResults;
use egui_kittest::kittest::Queryable as _;
#[test]
fn test_demo_app() {

View File

@@ -1,6 +1,6 @@
use std::fmt::Write as _;
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
use egui::epaint::TextShape;
use egui::load::SizedTexture;
@@ -174,7 +174,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let mut locked_fonts = fonts.lock();
c.bench_function("text_layout_uncached", |b| {
b.iter(|| {
use egui::epaint::text::{layout, LayoutJob};
use egui::epaint::text::{LayoutJob, layout};
let job = LayoutJob::simple(
LOREM_IPSUM_LONG.to_owned(),

View File

@@ -62,6 +62,7 @@ impl CodeExample {
}
ui.end_row();
#[expect(clippy::literal_string_with_formatting_args)]
show_code(ui, r#"ui.label(format!("{name} is {age}"));"#);
ui.label(format!("{name} is {age}"));
ui.end_row();

View File

@@ -1,8 +1,9 @@
use egui::{
Color32, Context, Pos2, Rect, Ui,
containers::{Frame, Window},
emath, epaint,
epaint::PathStroke,
hex_color, lerp, pos2, remap, vec2, Color32, Context, Pos2, Rect, Ui,
hex_color, lerp, pos2, remap, vec2,
};
#[derive(Default)]

View File

@@ -1,9 +1,9 @@
use std::collections::BTreeSet;
use super::About;
use crate::is_mobile;
use crate::Demo;
use crate::View as _;
use crate::is_mobile;
use egui::containers::menu;
use egui::style::StyleModifier;
use egui::{Context, Modifiers, ScrollArea, Ui};
@@ -370,7 +370,7 @@ fn file_menu_button(ui: &mut Ui) {
#[cfg(test)]
mod tests {
use crate::{demo::demo_app_windows::DemoGroups, Demo as _};
use crate::{Demo as _, demo::demo_app_windows::DemoGroups};
use egui_kittest::kittest::{NodeT as _, Queryable as _};
use egui_kittest::{Harness, SnapshotOptions, SnapshotResults};

View File

@@ -1,4 +1,4 @@
use egui::{vec2, Color32, Context, Frame, Id, Ui, Window};
use egui::{Color32, Context, Frame, Id, Ui, Window, vec2};
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]

View File

@@ -1,8 +1,8 @@
use super::{Demo, View};
use egui::{
vec2, Align, Align2, Checkbox, CollapsingHeader, Color32, ComboBox, Context, FontId, Resize,
RichText, Sense, Slider, Stroke, TextFormat, TextStyle, Ui, Vec2, Window,
Align, Align2, Checkbox, CollapsingHeader, Color32, ComboBox, Context, FontId, Resize,
RichText, Sense, Slider, Stroke, TextFormat, TextStyle, Ui, Vec2, Window, vec2,
};
/// Showcase some ui code

View File

@@ -162,10 +162,10 @@ impl crate::View for Modals {
#[cfg(test)]
mod tests {
use crate::demo::modals::Modals;
use crate::Demo as _;
use egui::accesskit::Role;
use crate::demo::modals::Modals;
use egui::Key;
use egui::accesskit::Role;
use egui_kittest::kittest::Queryable as _;
use egui_kittest::{Harness, SnapshotResults};

Some files were not shown because too many files have changed in this diff Show More