1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 05:10:03 -04:00

Merge branch 'master' of https://github.com/emilk/egui into multiples_viewports

This commit is contained in:
Konkitoman
2023-08-29 10:00:14 +03:00
41 changed files with 237 additions and 114 deletions

View File

@@ -29,4 +29,4 @@ jobs:
with:
mode: minimum
count: 1
labels: "CI, dependencies, docs and examples, ecolor, eframe, egui_extras, egui_glow, egui-wgpu, egui-winit, egui, epaint, plot, typo"
labels: "CI, dependencies, docs and examples, ecolor, eframe, egui_extras, egui_glow, egui_plot, egui-wgpu, egui-winit, egui, epaint, typo"

View File

@@ -5,7 +5,7 @@ Also see [`CONTRIBUTING.md`](CONTRIBUTING.md) for what to do before opening a PR
## Crate overview
The crates in this repository are: `egui, emath, epaint, egui_extras, egui-winit, egui_glium, egui_glow, egui_demo_lib, egui_demo_app`.
The crates in this repository are: `egui, emath, epaint, egui_extras, egui_plot, egui-winit, egui_glium, egui_glow, egui_demo_lib, egui_demo_app`.
### `egui`: The main GUI library.
Example code: `if ui.button("Click me").clicked() { … }`
@@ -24,6 +24,9 @@ Depends on `emath`.
### `egui_extras`
This adds additional features on top of `egui`.
### `egui_plot`
Plotting for `egui`.
### `egui-winit`
This crates provides bindings between [`egui`](https://github.com/emilk/egui) and [winit](https://crates.io/crates/winit).

View File

@@ -1,7 +1,7 @@
# egui changelog
All notable changes to the `egui` crate will be documented in this file.
NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG.md), [`egui-winit`](crates/egui-winit/CHANGELOG.md), [`egui_glium`](crates/egui_glium/CHANGELOG.md), [`egui_glow`](crates/egui_glow/CHANGELOG.md) and [`egui-wgpu`](crates/egui-wgpu/CHANGELOG.md) have their own changelogs!
NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`egui_plot`](crates/egui_plot/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG.md), [`egui-winit`](crates/egui-winit/CHANGELOG.md), [`egui_glium`](crates/egui_glium/CHANGELOG.md), [`egui_glow`](crates/egui_glow/CHANGELOG.md) and [`egui-wgpu`](crates/egui-wgpu/CHANGELOG.md) have their own changelogs!
This file is updated upon each release.
Changes since the last release can be found by running the `scripts/generate_changelog.py` script.

11
Cargo.lock generated
View File

@@ -1247,6 +1247,7 @@ dependencies = [
"document-features",
"egui",
"egui_extras",
"egui_plot",
"enum-map",
"log",
"serde",
@@ -1288,6 +1289,15 @@ dependencies = [
"web-sys",
]
[[package]]
name = "egui_plot"
version = "0.22.0"
dependencies = [
"document-features",
"egui",
"serde",
]
[[package]]
name = "ehttp"
version = "0.2.0"
@@ -3129,6 +3139,7 @@ name = "save_plot"
version = "0.1.0"
dependencies = [
"eframe",
"egui_plot",
"env_logger",
"image",
"rfd",

View File

@@ -6,6 +6,7 @@ members = [
"crates/egui_demo_lib",
"crates/egui_extras",
"crates/egui_glow",
"crates/egui_plot",
"crates/egui-wgpu",
"crates/egui-winit",
"crates/egui",

View File

@@ -473,6 +473,7 @@ pub fn install_canvas_events(runner_ref: &WebRunner) -> Result<(), JsValue> {
for i in 0..files.length() {
if let Some(file) = files.get(i) {
let name = file.name();
let mime = file.type_();
let last_modified = std::time::UNIX_EPOCH
+ std::time::Duration::from_millis(file.last_modified() as u64);
@@ -491,6 +492,7 @@ pub fn install_canvas_events(runner_ref: &WebRunner) -> Result<(), JsValue> {
runner_lock.input.raw.dropped_files.push(
egui::DroppedFile {
name,
mime,
last_modified: Some(last_modified),
bytes: Some(bytes.into()),
..Default::default()

View File

@@ -822,7 +822,7 @@ impl Renderer {
)
.expect("Failed to create staging buffer for index data");
let mut index_offset = 0;
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs.iter() {
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs {
match primitive {
Primitive::Mesh(mesh) => {
let size = mesh.indices.len() * std::mem::size_of::<u32>();
@@ -857,7 +857,7 @@ impl Renderer {
)
.expect("Failed to create staging buffer for vertex data");
let mut vertex_offset = 0;
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs.iter() {
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs {
match primitive {
Primitive::Mesh(mesh) => {
let size = mesh.vertices.len() * std::mem::size_of::<Vertex>();

View File

@@ -109,7 +109,9 @@ impl WindowSettings {
return;
}
let Some(inner_size_points) = self.inner_size_points else { return; };
let Some(inner_size_points) = self.inner_size_points else {
return;
};
if let Some(pos_px) = &mut self.inner_position_pixels {
clamp_pos_to_monitors(event_loop, inner_size_points, pos_px);

View File

@@ -176,6 +176,9 @@ pub struct DroppedFile {
/// Name of the file. Set by the `eframe` web backend.
pub name: String,
/// With the `eframe` web backend, this is set to the mime-type of the file (if available).
pub mime: String,
/// Set by the `eframe` web backend.
pub last_modified: Option<std::time::SystemTime>,

View File

@@ -220,9 +220,15 @@ impl GridLayout {
fn paint_row(&mut self, cursor: &mut Rect, painter: &Painter) {
// handle row color painting based on color-picker function
let Some(color_picker) = self.color_picker.as_ref() else { return };
let Some(row_color) = color_picker(self.row, &self.style) else { return };
let Some(height) = self.prev_state.row_height(self.row) else {return };
let Some(color_picker) = self.color_picker.as_ref() else {
return;
};
let Some(row_color) = color_picker(self.row, &self.style) else {
return;
};
let Some(height) = self.prev_state.row_height(self.row) else {
return;
};
// Paint background for coming row:
let size = Vec2::new(self.prev_state.full_width(self.spacing.x), height);
let rect = Rect::from_min_size(cursor.min, size);

View File

@@ -772,7 +772,7 @@ impl PointerState {
/// Latest reported pointer position.
/// When tapping a touch screen, this will be `None`.
#[inline(always)]
pub(crate) fn latest_pos(&self) -> Option<Pos2> {
pub fn latest_pos(&self) -> Option<Pos2> {
self.latest_pos
}

View File

@@ -329,6 +329,8 @@ pub mod widgets;
#[cfg(feature = "accesskit")]
pub use accesskit;
pub use ahash;
pub use epaint;
pub use epaint::ecolor;
pub use epaint::emath;

View File

@@ -809,7 +809,8 @@ impl Ui {
self.interact(rect, id, sense)
}
pub(crate) fn advance_cursor_after_rect(&mut self, rect: Rect) -> Id {
/// Allocate a rect without interacting with it.
pub fn advance_cursor_after_rect(&mut self, rect: Rect) -> Id {
egui_assert!(!rect.any_nan());
let item_spacing = self.spacing().item_spacing;
self.placer.advance_after_rects(rect, rect, item_spacing);

View File

@@ -12,7 +12,6 @@ pub(crate) mod drag_value;
mod hyperlink;
mod image;
mod label;
pub mod plot;
mod progress_bar;
mod selected_label;
mod separator;

View File

@@ -12,6 +12,7 @@ enum ProgressBarText {
pub struct ProgressBar {
progress: f32,
desired_width: Option<f32>,
desired_height: Option<f32>,
text: Option<ProgressBarText>,
fill: Option<Color32>,
animate: bool,
@@ -23,6 +24,7 @@ impl ProgressBar {
Self {
progress: progress.clamp(0.0, 1.0),
desired_width: None,
desired_height: None,
text: None,
fill: None,
animate: false,
@@ -35,6 +37,12 @@ impl ProgressBar {
self
}
/// The desired height of the bar. Will use the default interaction size if not set.
pub fn desired_height(mut self, desired_height: f32) -> Self {
self.desired_height = Some(desired_height);
self
}
/// The fill color of the bar.
pub fn fill(mut self, color: Color32) -> Self {
self.fill = Some(color);
@@ -67,6 +75,7 @@ impl Widget for ProgressBar {
let ProgressBar {
progress,
desired_width,
desired_height,
text,
fill,
animate,
@@ -76,7 +85,7 @@ impl Widget for ProgressBar {
let desired_width =
desired_width.unwrap_or_else(|| ui.available_size_before_wrap().x.at_least(96.0));
let height = ui.spacing().interact_size.y;
let height = desired_height.unwrap_or(ui.spacing().interact_size.y);
let (outer_rect, response) =
ui.allocate_exact_size(vec2(desired_width, height), Sense::hover());

View File

@@ -513,9 +513,18 @@ impl WrapApp {
} else {
"???".to_owned()
};
if let Some(bytes) = &file.bytes {
write!(info, " ({} bytes)", bytes.len()).ok();
let mut additional_info = vec![];
if !file.mime.is_empty() {
additional_info.push(format!("type: {}", file.mime));
}
if let Some(bytes) = &file.bytes {
additional_info.push(format!("{} bytes", bytes.len()));
}
if !additional_info.is_empty() {
info += &format!(" ({})", additional_info.join(", "));
}
ui.label(info);
}
});

View File

@@ -23,8 +23,10 @@ all-features = true
default = []
chrono = ["egui_extras/datepicker", "dep:chrono"]
## Allow serialization using [`serde`](https://docs.rs/serde).
serde = ["egui/serde", "dep:serde"]
serde = ["egui/serde", "egui_plot/serde", "dep:serde"]
## Enable better syntax highlighting using [`syntect`](https://docs.rs/syntect).
syntax_highlighting = ["syntect"]
@@ -32,6 +34,7 @@ syntax_highlighting = ["syntect"]
[dependencies]
egui = { version = "0.22.0", path = "../egui", default-features = false }
egui_extras = { version = "0.22.0", path = "../egui_extras" }
egui_plot = { version = "0.22.0", path = "../egui_plot" }
enum-map = { version = "2", features = ["serde"] }
log = { version = "0.4", features = ["std"] }
unicode_names2 = { version = "0.6.0", default-features = false }

View File

@@ -122,7 +122,7 @@ impl super::View for ContextMenus {
impl ContextMenus {
fn example_plot(&self, ui: &mut egui::Ui) -> egui::Response {
use egui::plot::{Line, PlotPoints};
use egui_plot::{Line, PlotPoints};
let n = 128;
let line = Line::new(
(0..=n)
@@ -137,7 +137,7 @@ impl ContextMenus {
})
.collect::<PlotPoints>(),
);
egui::plot::Plot::new("example_plot")
egui_plot::Plot::new("example_plot")
.show_axes(self.show_axes)
.allow_drag(self.allow_drag)
.allow_zoom(self.allow_zoom)

View File

@@ -3,7 +3,7 @@ use std::ops::RangeInclusive;
use egui::*;
use egui::plot::{
use egui_plot::{
Arrows, AxisBools, AxisHints, Bar, BarChart, BoxElem, BoxPlot, BoxSpread, CoordinatesFormatter,
Corner, GridInput, GridMark, HLine, Legend, Line, LineStyle, MarkerShape, Plot, PlotImage,
PlotPoint, PlotPoints, PlotResponse, Points, Polygon, Text, VLine,
@@ -575,7 +575,7 @@ impl CustomAxesDemo {
.max_digits(4),
AxisHints::default()
.label("Absolute")
.placement(plot::HPlacement::Right),
.placement(egui_plot::HPlacement::Right),
];
Plot::new("custom_axes")
.data_aspect(2.0 * MINS_PER_DAY as f32)
@@ -636,7 +636,7 @@ impl LinkedAxesDemo {
))
}
fn configure_plot(plot_ui: &mut plot::PlotUi) {
fn configure_plot(plot_ui: &mut egui_plot::PlotUi) {
plot_ui.line(LinkedAxesDemo::line_with_slope(0.5));
plot_ui.line(LinkedAxesDemo::line_with_slope(1.0));
plot_ui.line(LinkedAxesDemo::line_with_slope(2.0));
@@ -671,7 +671,7 @@ impl LinkedAxesDemo {
.height(250.0)
.y_axis_width(3)
.y_axis_label("y")
.y_axis_position(plot::HPlacement::Right)
.y_axis_position(egui_plot::HPlacement::Right)
.link_axis(link_group_id, self.link_x, self.link_y)
.link_cursor(link_group_id, self.link_cursor_x, self.link_cursor_y)
.show(ui, LinkedAxesDemo::configure_plot);

View File

@@ -258,7 +258,7 @@ impl WidgetGallery {
}
fn example_plot(ui: &mut egui::Ui) -> egui::Response {
use egui::plot::{Line, PlotPoints};
use egui_plot::{Line, PlotPoints};
let n = 128;
let line_points: PlotPoints = (0..=n)
.map(|i| {
@@ -268,7 +268,7 @@ fn example_plot(ui: &mut egui::Ui) -> egui::Response {
})
.collect();
let line = Line::new(line_points);
egui::plot::Plot::new("example_plot")
egui_plot::Plot::new("example_plot")
.height(32.0)
.show_axes(false)
.data_aspect(1.0)

View File

@@ -24,7 +24,7 @@ fn month_data(year: i32, month: u32) -> Vec<Week> {
if start.weekday() == Weekday::Sun {
weeks.push(Week {
number: start.iso_week().week() as u8,
days: week.drain(..).collect(),
days: std::mem::take(&mut week),
});
}
start = start.checked_add_signed(Duration::days(1)).unwrap();

View File

@@ -0,0 +1,5 @@
# Changelog for egui_plot
All notable changes to the `egui_plot` integration will be noted in this file.
This file is updated upon each release.
Changes since the last release can be found by running the `scripts/generate_changelog.py` script.

View File

@@ -0,0 +1,42 @@
[package]
name = "egui_plot"
version = "0.22.0"
authors = [
"Dominik Rössler <dominik@freshx.de>",
"Emil Ernerfeldt <emil.ernerfeldt@gmail.com>",
"René Rössler <rene@freshx.de>",
]
description = "Immediate mode plotting for the egui GUI library"
edition = "2021"
rust-version = "1.67"
homepage = "https://github.com/emilk/egui"
license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/emilk/egui"
categories = ["visualization", "gui"]
keywords = ["egui", "plot", "plotting"]
include = ["../LICENSE-APACHE", "../LICENSE-MIT", "**/*.rs", "Cargo.toml"]
[package.metadata.docs.rs]
all-features = true
[lib]
[features]
default = []
## Allow serialization using [`serde`](https://docs.rs/serde).
serde = ["dep:serde", "egui/serde"]
[dependencies]
egui = { version = "0.22.0", path = "../egui", default-features = false }
#! ### Optional dependencies
## Enable this when generating docs.
document-features = { version = "0.2", optional = true }
serde = { version = "1", optional = true, features = ["derive"] }

View File

@@ -0,0 +1,9 @@
# egui_plot
[![Latest version](https://img.shields.io/crates/v/egui_plot.svg)](https://crates.io/crates/egui_plot)
[![Documentation](https://docs.rs/egui_plot/badge.svg)](https://docs.rs/egui_plot)
[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
![MIT](https://img.shields.io/badge/license-MIT-blue.svg)
![Apache](https://img.shields.io/badge/license-Apache-blue.svg)
Immediate mode plotting for [`egui`](https://github.com/emilk/egui).

View File

@@ -1,9 +1,7 @@
use std::{fmt::Debug, ops::RangeInclusive, sync::Arc};
use epaint::{
emath::{remap_clamp, round_to_decimals},
Pos2, Rect, Shape, Stroke, TextShape,
};
use egui::emath::{remap_clamp, round_to_decimals, Pos2, Rect};
use egui::epaint::{Shape, Stroke, TextShape};
use crate::{Response, Sense, TextStyle, Ui, WidgetText};

View File

@@ -1,8 +1,8 @@
use crate::emath::NumExt;
use crate::epaint::{Color32, RectShape, Rounding, Shape, Stroke};
use egui::emath::NumExt;
use egui::epaint::{Color32, RectShape, Rounding, Shape, Stroke};
use super::{add_rulers_and_text, highlighted_color, Orientation, PlotConfig, RectElement};
use crate::plot::{BarChart, Cursor, PlotPoint, PlotTransform};
use crate::{BarChart, Cursor, PlotPoint, PlotTransform};
/// One bar in a [`BarChart`]. Potentially floating, allowing stacked bar charts.
/// Width can be changed to allow variable-width histograms.
@@ -185,6 +185,6 @@ impl RectElement for Bar {
Orientation::Vertical => scale[1],
};
let decimals = ((-scale.abs().log10()).ceil().at_least(0.0) as usize).at_most(6);
crate::plot::format_number(self.value, decimals)
crate::format_number(self.value, decimals)
}
}

View File

@@ -1,8 +1,9 @@
use crate::emath::NumExt;
use crate::epaint::{Color32, RectShape, Rounding, Shape, Stroke};
use egui::emath::NumExt as _;
use egui::epaint::{Color32, RectShape, Rounding, Shape, Stroke};
use crate::{BoxPlot, Cursor, PlotPoint, PlotTransform};
use super::{add_rulers_and_text, highlighted_color, Orientation, PlotConfig, RectElement};
use crate::plot::{BoxPlot, Cursor, PlotPoint, PlotTransform};
/// Contains the values of a single box in a box plot.
#[derive(Clone, Debug, PartialEq)]

View File

@@ -2,8 +2,7 @@
use std::ops::RangeInclusive;
use epaint::util::FloatOrd;
use epaint::Mesh;
use epaint::{emath::Rot2, util::FloatOrd, Mesh};
use crate::*;
@@ -188,10 +187,10 @@ impl PlotItem for HLine {
// Round to minimize aliasing:
let points = vec![
ui.ctx().round_pos_to_pixels(
ui.painter().round_pos_to_pixels(
transform.position_from_point(&PlotPoint::new(transform.bounds().min[0], *y)),
),
ui.ctx().round_pos_to_pixels(
ui.painter().round_pos_to_pixels(
transform.position_from_point(&PlotPoint::new(transform.bounds().max[0], *y)),
),
];
@@ -304,10 +303,10 @@ impl PlotItem for VLine {
// Round to minimize aliasing:
let points = vec![
ui.ctx().round_pos_to_pixels(
ui.painter().round_pos_to_pixels(
transform.position_from_point(&PlotPoint::new(*x, transform.bounds().min[1])),
),
ui.ctx().round_pos_to_pixels(
ui.painter().round_pos_to_pixels(
transform.position_from_point(&PlotPoint::new(*x, transform.bounds().max[1])),
),
];
@@ -517,7 +516,7 @@ pub struct Polygon {
pub(super) stroke: Stroke,
pub(super) name: String,
pub(super) highlight: bool,
pub(super) fill_alpha: f32,
pub(super) fill_color: Option<Color32>,
pub(super) style: LineStyle,
}
@@ -528,7 +527,7 @@ impl Polygon {
stroke: Stroke::new(1.0, Color32::TRANSPARENT),
name: Default::default(),
highlight: false,
fill_alpha: DEFAULT_FILL_ALPHA,
fill_color: None,
style: LineStyle::Solid,
}
}
@@ -552,15 +551,21 @@ impl Polygon {
self
}
/// Stroke color. Default is `Color32::TRANSPARENT` which means a color will be auto-assigned.
#[deprecated = "Use `fill_color`."]
#[allow(unused, clippy::needless_pass_by_value)]
pub fn color(mut self, color: impl Into<Color32>) -> Self {
self.stroke.color = color.into();
self
}
/// Alpha of the filled area.
pub fn fill_alpha(mut self, alpha: impl Into<f32>) -> Self {
self.fill_alpha = alpha.into();
#[deprecated = "Use `fill_color`."]
#[allow(unused, clippy::needless_pass_by_value)]
pub fn fill_alpha(mut self, _alpha: impl Into<f32>) -> Self {
self
}
/// Fill color. Defaults to the stroke color with added transparency.
pub fn fill_color(mut self, color: impl Into<Color32>) -> Self {
self.fill_color = Some(color.into());
self
}
@@ -589,24 +594,20 @@ impl PlotItem for Polygon {
series,
stroke,
highlight,
mut fill_alpha,
fill_color,
style,
..
} = self;
if *highlight {
fill_alpha = (2.0 * fill_alpha).at_most(1.0);
}
let mut values_tf: Vec<_> = series
.points()
.iter()
.map(|v| transform.position_from_point(v))
.collect();
let fill = Rgba::from(stroke.color).to_opaque().multiply(fill_alpha);
let fill_color = fill_color.unwrap_or(stroke.color.linear_multiply(DEFAULT_FILL_ALPHA));
let shape = Shape::convex_polygon(values_tf.clone(), fill, Stroke::NONE);
let shape = Shape::convex_polygon(values_tf.clone(), fill_color, Stroke::NONE);
shapes.push(shape);
values_tf.push(*values_tf.first().unwrap());
style.style_line(values_tf, *stroke, *highlight, shapes);
@@ -1135,11 +1136,11 @@ pub struct PlotImage {
pub(super) texture_id: TextureId,
pub(super) uv: Rect,
pub(super) size: Vec2,
pub(crate) rotation: f64,
pub(super) bg_fill: Color32,
pub(super) tint: Color32,
pub(super) highlight: bool,
pub(super) name: String,
pub(crate) rotation: Option<(f32, Vec2)>,
}
impl PlotImage {
@@ -1156,9 +1157,9 @@ impl PlotImage {
texture_id: texture_id.into(),
uv: Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
size: size.into(),
rotation: 0.0,
bg_fill: Default::default(),
tint: Color32::WHITE,
rotation: None,
}
}
@@ -1198,14 +1199,9 @@ impl PlotImage {
self
}
/// Rotate the image about an origin by some angle
///
/// Positive angle is clockwise.
/// Origin is a vector in normalized UV space ((0,0) in top-left, (1,1) bottom right).
///
/// To rotate about the center you can pass `Vec2::splat(0.5)` as the origin.
pub fn rotate(mut self, angle: f32, origin: Vec2) -> Self {
self.rotation = Some((angle, origin));
/// Rotate the image counter-clockwise around its center by an angle in radians.
pub fn rotate(mut self, angle: f64) -> Self {
self.rotation = angle;
self
}
}
@@ -1214,6 +1210,7 @@ impl PlotItem for PlotImage {
fn shapes(&self, ui: &mut Ui, transform: &PlotTransform, shapes: &mut Vec<Shape>) {
let Self {
position,
rotation,
texture_id,
uv,
size,
@@ -1222,31 +1219,40 @@ impl PlotItem for PlotImage {
highlight,
..
} = self;
let rect = {
let image_screen_rect = {
let left_top = PlotPoint::new(
position.x as f32 - size.x / 2.0,
position.y as f32 - size.y / 2.0,
position.x - 0.5 * size.x as f64,
position.y - 0.5 * size.y as f64,
);
let right_bottom = PlotPoint::new(
position.x as f32 + size.x / 2.0,
position.y as f32 + size.y / 2.0,
position.x + 0.5 * size.x as f64,
position.y + 0.5 * size.y as f64,
);
let left_top_tf = transform.position_from_point(&left_top);
let right_bottom_tf = transform.position_from_point(&right_bottom);
Rect::from_two_pos(left_top_tf, right_bottom_tf)
let left_top_screen = transform.position_from_point(&left_top);
let right_bottom_screen = transform.position_from_point(&right_bottom);
Rect::from_two_pos(left_top_screen, right_bottom_screen)
};
let mut image = Image::new(*texture_id, *size)
let screen_rotation = -*rotation as f32;
Image::new(*texture_id, image_screen_rect.size())
.bg_fill(*bg_fill)
.tint(*tint)
.uv(*uv);
if let Some((angle, origin)) = self.rotation {
image = image.rotate(angle, origin);
}
image.paint_at(ui, rect);
.uv(*uv)
.rotate(screen_rotation, Vec2::splat(0.5))
.paint_at(ui, image_screen_rect);
if *highlight {
shapes.push(Shape::rect_stroke(
rect,
0.0,
let center = image_screen_rect.center();
let rotation = Rot2::from_angle(screen_rotation);
let outline = [
image_screen_rect.right_bottom(),
image_screen_rect.right_top(),
image_screen_rect.left_top(),
image_screen_rect.left_bottom(),
]
.iter()
.map(|point| center + rotation * (*point - center))
.collect();
shapes.push(Shape::closed_line(
outline,
Stroke::new(1.0, ui.visuals().strong_text_color()),
));
}

View File

@@ -1,7 +1,9 @@
use egui::emath::NumExt as _;
use egui::epaint::{Color32, Rgba, Stroke};
use crate::transform::{PlotBounds, PlotTransform};
use super::{Orientation, PlotPoint};
use crate::plot::transform::{PlotBounds, PlotTransform};
use epaint::emath::NumExt;
use epaint::{Color32, Rgba, Stroke};
/// Trait that abstracts from rectangular 'Value'-like elements, such as bars or boxes
pub(super) trait RectElement {

View File

@@ -1,7 +1,8 @@
use epaint::{Pos2, Shape, Stroke, Vec2};
use std::ops::{Bound, RangeBounds, RangeInclusive};
use crate::plot::transform::PlotBounds;
use egui::{Pos2, Shape, Stroke, Vec2};
use crate::transform::PlotBounds;
/// A point coordinate in the plot.
///

View File

@@ -1,8 +1,12 @@
//! Simple plotting library.
//!
//! ## Feature flags
#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
//!
use std::{ops::RangeInclusive, sync::Arc};
use ahash::HashMap;
use egui::ahash::HashMap;
use epaint::util::FloatOrd;
use epaint::Hsva;
@@ -10,7 +14,7 @@ use axis::AxisWidget;
use items::PlotItem;
use legend::LegendWidget;
use crate::*;
use egui::*;
pub use items::{
Arrows, Bar, BarChart, BoxElem, BoxPlot, BoxSpread, HLine, Line, LineStyle, MarkerShape,
@@ -182,7 +186,7 @@ pub struct PlotResponse<R> {
///
/// ```
/// # egui::__run_test_ui(|ui| {
/// use egui::plot::{Line, Plot, PlotPoints};
/// use egui_plot::{Line, Plot, PlotPoints};
/// let sin: PlotPoints = (0..1000).map(|i| {
/// let x = i as f64 * 0.01;
/// [x, x.sin()]
@@ -394,7 +398,7 @@ impl Plot {
///
/// ```
/// # egui::__run_test_ui(|ui| {
/// use egui::plot::{Line, Plot, PlotPoints};
/// use egui_plot::{Line, Plot, PlotPoints};
/// let sin: PlotPoints = (0..1000).map(|i| {
/// let x = i as f64 * 0.01;
/// [x, x.sin()]
@@ -443,7 +447,7 @@ impl Plot {
/// For example, if x = 80..=230 is visible and you want big marks at steps of
/// 100 and small ones at 25, you can return:
/// ```no_run
/// # use egui::plot::GridMark;
/// # use egui_plot::GridMark;
/// vec![
/// // 100s
/// GridMark { value: 100.0, step_size: 100.0 },
@@ -1781,8 +1785,8 @@ impl PreparedPlot {
if self.sharp_grid_lines {
// Round to avoid aliasing
p0 = ui.ctx().round_pos_to_pixels(p0);
p1 = ui.ctx().round_pos_to_pixels(p1);
p0 = ui.painter().round_pos_to_pixels(p0);
p1 = ui.painter().round_pos_to_pixels(p1);
}
shapes.push((
@@ -1851,7 +1855,7 @@ impl PreparedPlot {
/// Returns next bigger power in given base
/// e.g.
/// ```ignore
/// use egui::plot::next_power;
/// use egui_plot::next_power;
/// assert_eq!(next_power(0.01, 10.0), 0.01);
/// assert_eq!(next_power(0.02, 10.0), 0.1);
/// assert_eq!(next_power(0.2, 10.0), 1);

View File

@@ -24,6 +24,7 @@ default = []
## Enable additional checks if debug assertions are enabled (debug builds).
extra_debug_asserts = []
## Always enable additional checks.
extra_asserts = []

View File

@@ -215,7 +215,7 @@ impl TexturesDelta {
}
pub fn append(&mut self, mut newer: TexturesDelta) {
self.set.extend(newer.set.into_iter());
self.set.extend(newer.set);
self.free.append(&mut newer.free);
}

View File

@@ -22,6 +22,7 @@ unmaintained = "warn"
yanked = "deny"
ignore = [
"RUSTSEC-2020-0071", # https://rustsec.org/advisories/RUSTSEC-2020-0071 - chrono/time: Potential segfault in the time crate
"RUSTSEC-2023-0052", # https://rustsec.org/advisories/RUSTSEC-2023-0052 - can be fixed by `cargo update -p ureq`, but then we run into duplicate crates: https://github.com/algesten/ureq/issues/653
]
[bans]

View File

@@ -62,10 +62,18 @@ impl eframe::App for MyApp {
} else {
"???".to_owned()
};
if let Some(bytes) = &file.bytes {
use std::fmt::Write as _;
write!(info, " ({} bytes)", bytes.len()).ok();
let mut additional_info = vec![];
if !file.mime.is_empty() {
additional_info.push(format!("type: {}", file.mime));
}
if let Some(bytes) = &file.bytes {
additional_info.push(format!("{} bytes", bytes.len()));
}
if !additional_info.is_empty() {
info += &format!(" ({})", additional_info.join(", "));
}
ui.label(info);
}
});

View File

@@ -11,6 +11,7 @@ publish = false
eframe = { path = "../../crates/eframe", features = [
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
] }
egui_plot = { path = "../../crates/egui_plot" }
image = { version = "0.24", default-features = false, features = ["png"] }
rfd = "0.11.0"
env_logger = "0.10"

View File

@@ -1,8 +1,8 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
use eframe::egui::plot::{Legend, Line, Plot, PlotPoints};
use eframe::egui::ColorImage;
use eframe::egui::{self, ViewportRender};
use egui_plot::{Legend, Line, Plot, PlotPoints};
fn main() -> Result<(), eframe::Error> {
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).

View File

@@ -131,6 +131,7 @@ def main() -> None:
"ecolor",
"eframe",
"egui_extras",
"egui_plot",
"egui_glow",
"egui-wgpu",
"egui-winit",
@@ -141,8 +142,6 @@ def main() -> None:
unsorted_prs = []
unsorted_commits = []
plot = []
for commit_info, pr_info in zip(commit_infos, pr_infos):
hexsha = commit_info.hexsha
title = commit_info.title
@@ -170,14 +169,11 @@ def main() -> None:
continue # We get so many typo PRs. Let's not flood the changelog with them.
added = False
if 'plot' in labels:
plot.append(summary)
added = True
else:
for crate in crate_names:
if crate in labels:
sections.setdefault(crate, []).append(summary)
added = True
for crate in crate_names:
if crate in labels:
sections.setdefault(crate, []).append(summary)
added = True
if not added:
if not any(label in labels for label in ignore_labels):
@@ -188,9 +184,6 @@ def main() -> None:
if crate in sections:
summary = sections[crate]
print_section(crate, summary)
if crate == 'egui':
if 0 < len(plot):
print_section("egui plot", plot)
print_section("Unsorted PRs", unsorted_prs)
print_section("Unsorted commits", unsorted_commits)