mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 14:50:03 -04:00
Merge branch 'master' of https://github.com/emilk/egui into multiples_viewports
This commit is contained in:
2
.github/workflows/labels.yml
vendored
2
.github/workflows/labels.yml
vendored
@@ -29,4 +29,4 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
mode: minimum
|
mode: minimum
|
||||||
count: 1
|
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"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Also see [`CONTRIBUTING.md`](CONTRIBUTING.md) for what to do before opening a PR
|
|||||||
|
|
||||||
|
|
||||||
## Crate overview
|
## 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.
|
### `egui`: The main GUI library.
|
||||||
Example code: `if ui.button("Click me").clicked() { … }`
|
Example code: `if ui.button("Click me").clicked() { … }`
|
||||||
@@ -24,6 +24,9 @@ Depends on `emath`.
|
|||||||
### `egui_extras`
|
### `egui_extras`
|
||||||
This adds additional features on top of `egui`.
|
This adds additional features on top of `egui`.
|
||||||
|
|
||||||
|
### `egui_plot`
|
||||||
|
Plotting for `egui`.
|
||||||
|
|
||||||
### `egui-winit`
|
### `egui-winit`
|
||||||
This crates provides bindings between [`egui`](https://github.com/emilk/egui) and [winit](https://crates.io/crates/winit).
|
This crates provides bindings between [`egui`](https://github.com/emilk/egui) and [winit](https://crates.io/crates/winit).
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# egui changelog
|
# egui changelog
|
||||||
All notable changes to the `egui` crate will be documented in this file.
|
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.
|
This file is updated upon each release.
|
||||||
Changes since the last release can be found by running the `scripts/generate_changelog.py` script.
|
Changes since the last release can be found by running the `scripts/generate_changelog.py` script.
|
||||||
|
|||||||
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -1247,6 +1247,7 @@ dependencies = [
|
|||||||
"document-features",
|
"document-features",
|
||||||
"egui",
|
"egui",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
|
"egui_plot",
|
||||||
"enum-map",
|
"enum-map",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -1288,6 +1289,15 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui_plot"
|
||||||
|
version = "0.22.0"
|
||||||
|
dependencies = [
|
||||||
|
"document-features",
|
||||||
|
"egui",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ehttp"
|
name = "ehttp"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -3129,6 +3139,7 @@ name = "save_plot"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"eframe",
|
"eframe",
|
||||||
|
"egui_plot",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"image",
|
"image",
|
||||||
"rfd",
|
"rfd",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ members = [
|
|||||||
"crates/egui_demo_lib",
|
"crates/egui_demo_lib",
|
||||||
"crates/egui_extras",
|
"crates/egui_extras",
|
||||||
"crates/egui_glow",
|
"crates/egui_glow",
|
||||||
|
"crates/egui_plot",
|
||||||
"crates/egui-wgpu",
|
"crates/egui-wgpu",
|
||||||
"crates/egui-winit",
|
"crates/egui-winit",
|
||||||
"crates/egui",
|
"crates/egui",
|
||||||
|
|||||||
@@ -473,6 +473,7 @@ pub fn install_canvas_events(runner_ref: &WebRunner) -> Result<(), JsValue> {
|
|||||||
for i in 0..files.length() {
|
for i in 0..files.length() {
|
||||||
if let Some(file) = files.get(i) {
|
if let Some(file) = files.get(i) {
|
||||||
let name = file.name();
|
let name = file.name();
|
||||||
|
let mime = file.type_();
|
||||||
let last_modified = std::time::UNIX_EPOCH
|
let last_modified = std::time::UNIX_EPOCH
|
||||||
+ std::time::Duration::from_millis(file.last_modified() as u64);
|
+ 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(
|
runner_lock.input.raw.dropped_files.push(
|
||||||
egui::DroppedFile {
|
egui::DroppedFile {
|
||||||
name,
|
name,
|
||||||
|
mime,
|
||||||
last_modified: Some(last_modified),
|
last_modified: Some(last_modified),
|
||||||
bytes: Some(bytes.into()),
|
bytes: Some(bytes.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|||||||
@@ -822,7 +822,7 @@ impl Renderer {
|
|||||||
)
|
)
|
||||||
.expect("Failed to create staging buffer for index data");
|
.expect("Failed to create staging buffer for index data");
|
||||||
let mut index_offset = 0;
|
let mut index_offset = 0;
|
||||||
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs.iter() {
|
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs {
|
||||||
match primitive {
|
match primitive {
|
||||||
Primitive::Mesh(mesh) => {
|
Primitive::Mesh(mesh) => {
|
||||||
let size = mesh.indices.len() * std::mem::size_of::<u32>();
|
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");
|
.expect("Failed to create staging buffer for vertex data");
|
||||||
let mut vertex_offset = 0;
|
let mut vertex_offset = 0;
|
||||||
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs.iter() {
|
for epaint::ClippedPrimitive { primitive, .. } in paint_jobs {
|
||||||
match primitive {
|
match primitive {
|
||||||
Primitive::Mesh(mesh) => {
|
Primitive::Mesh(mesh) => {
|
||||||
let size = mesh.vertices.len() * std::mem::size_of::<Vertex>();
|
let size = mesh.vertices.len() * std::mem::size_of::<Vertex>();
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ impl WindowSettings {
|
|||||||
return;
|
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 {
|
if let Some(pos_px) = &mut self.inner_position_pixels {
|
||||||
clamp_pos_to_monitors(event_loop, inner_size_points, pos_px);
|
clamp_pos_to_monitors(event_loop, inner_size_points, pos_px);
|
||||||
|
|||||||
@@ -176,6 +176,9 @@ pub struct DroppedFile {
|
|||||||
/// Name of the file. Set by the `eframe` web backend.
|
/// Name of the file. Set by the `eframe` web backend.
|
||||||
pub name: String,
|
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.
|
/// Set by the `eframe` web backend.
|
||||||
pub last_modified: Option<std::time::SystemTime>,
|
pub last_modified: Option<std::time::SystemTime>,
|
||||||
|
|
||||||
|
|||||||
@@ -220,9 +220,15 @@ impl GridLayout {
|
|||||||
|
|
||||||
fn paint_row(&mut self, cursor: &mut Rect, painter: &Painter) {
|
fn paint_row(&mut self, cursor: &mut Rect, painter: &Painter) {
|
||||||
// handle row color painting based on color-picker function
|
// handle row color painting based on color-picker function
|
||||||
let Some(color_picker) = self.color_picker.as_ref() else { return };
|
let Some(color_picker) = self.color_picker.as_ref() else {
|
||||||
let Some(row_color) = color_picker(self.row, &self.style) else { return };
|
return;
|
||||||
let Some(height) = self.prev_state.row_height(self.row) 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:
|
// Paint background for coming row:
|
||||||
let size = Vec2::new(self.prev_state.full_width(self.spacing.x), height);
|
let size = Vec2::new(self.prev_state.full_width(self.spacing.x), height);
|
||||||
let rect = Rect::from_min_size(cursor.min, size);
|
let rect = Rect::from_min_size(cursor.min, size);
|
||||||
|
|||||||
@@ -772,7 +772,7 @@ impl PointerState {
|
|||||||
/// Latest reported pointer position.
|
/// Latest reported pointer position.
|
||||||
/// When tapping a touch screen, this will be `None`.
|
/// When tapping a touch screen, this will be `None`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn latest_pos(&self) -> Option<Pos2> {
|
pub fn latest_pos(&self) -> Option<Pos2> {
|
||||||
self.latest_pos
|
self.latest_pos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -329,6 +329,8 @@ pub mod widgets;
|
|||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
pub use accesskit;
|
pub use accesskit;
|
||||||
|
|
||||||
|
pub use ahash;
|
||||||
|
|
||||||
pub use epaint;
|
pub use epaint;
|
||||||
pub use epaint::ecolor;
|
pub use epaint::ecolor;
|
||||||
pub use epaint::emath;
|
pub use epaint::emath;
|
||||||
|
|||||||
@@ -809,7 +809,8 @@ impl Ui {
|
|||||||
self.interact(rect, id, sense)
|
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());
|
egui_assert!(!rect.any_nan());
|
||||||
let item_spacing = self.spacing().item_spacing;
|
let item_spacing = self.spacing().item_spacing;
|
||||||
self.placer.advance_after_rects(rect, rect, item_spacing);
|
self.placer.advance_after_rects(rect, rect, item_spacing);
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ pub(crate) mod drag_value;
|
|||||||
mod hyperlink;
|
mod hyperlink;
|
||||||
mod image;
|
mod image;
|
||||||
mod label;
|
mod label;
|
||||||
pub mod plot;
|
|
||||||
mod progress_bar;
|
mod progress_bar;
|
||||||
mod selected_label;
|
mod selected_label;
|
||||||
mod separator;
|
mod separator;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ enum ProgressBarText {
|
|||||||
pub struct ProgressBar {
|
pub struct ProgressBar {
|
||||||
progress: f32,
|
progress: f32,
|
||||||
desired_width: Option<f32>,
|
desired_width: Option<f32>,
|
||||||
|
desired_height: Option<f32>,
|
||||||
text: Option<ProgressBarText>,
|
text: Option<ProgressBarText>,
|
||||||
fill: Option<Color32>,
|
fill: Option<Color32>,
|
||||||
animate: bool,
|
animate: bool,
|
||||||
@@ -23,6 +24,7 @@ impl ProgressBar {
|
|||||||
Self {
|
Self {
|
||||||
progress: progress.clamp(0.0, 1.0),
|
progress: progress.clamp(0.0, 1.0),
|
||||||
desired_width: None,
|
desired_width: None,
|
||||||
|
desired_height: None,
|
||||||
text: None,
|
text: None,
|
||||||
fill: None,
|
fill: None,
|
||||||
animate: false,
|
animate: false,
|
||||||
@@ -35,6 +37,12 @@ impl ProgressBar {
|
|||||||
self
|
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.
|
/// The fill color of the bar.
|
||||||
pub fn fill(mut self, color: Color32) -> Self {
|
pub fn fill(mut self, color: Color32) -> Self {
|
||||||
self.fill = Some(color);
|
self.fill = Some(color);
|
||||||
@@ -67,6 +75,7 @@ impl Widget for ProgressBar {
|
|||||||
let ProgressBar {
|
let ProgressBar {
|
||||||
progress,
|
progress,
|
||||||
desired_width,
|
desired_width,
|
||||||
|
desired_height,
|
||||||
text,
|
text,
|
||||||
fill,
|
fill,
|
||||||
animate,
|
animate,
|
||||||
@@ -76,7 +85,7 @@ impl Widget for ProgressBar {
|
|||||||
|
|
||||||
let desired_width =
|
let desired_width =
|
||||||
desired_width.unwrap_or_else(|| ui.available_size_before_wrap().x.at_least(96.0));
|
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) =
|
let (outer_rect, response) =
|
||||||
ui.allocate_exact_size(vec2(desired_width, height), Sense::hover());
|
ui.allocate_exact_size(vec2(desired_width, height), Sense::hover());
|
||||||
|
|
||||||
|
|||||||
@@ -513,9 +513,18 @@ impl WrapApp {
|
|||||||
} else {
|
} else {
|
||||||
"???".to_owned()
|
"???".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);
|
ui.label(info);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ all-features = true
|
|||||||
default = []
|
default = []
|
||||||
|
|
||||||
chrono = ["egui_extras/datepicker", "dep:chrono"]
|
chrono = ["egui_extras/datepicker", "dep:chrono"]
|
||||||
|
|
||||||
## Allow serialization using [`serde`](https://docs.rs/serde).
|
## 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).
|
## Enable better syntax highlighting using [`syntect`](https://docs.rs/syntect).
|
||||||
syntax_highlighting = ["syntect"]
|
syntax_highlighting = ["syntect"]
|
||||||
|
|
||||||
@@ -32,6 +34,7 @@ syntax_highlighting = ["syntect"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
egui = { version = "0.22.0", path = "../egui", default-features = false }
|
egui = { version = "0.22.0", path = "../egui", default-features = false }
|
||||||
egui_extras = { version = "0.22.0", path = "../egui_extras" }
|
egui_extras = { version = "0.22.0", path = "../egui_extras" }
|
||||||
|
egui_plot = { version = "0.22.0", path = "../egui_plot" }
|
||||||
enum-map = { version = "2", features = ["serde"] }
|
enum-map = { version = "2", features = ["serde"] }
|
||||||
log = { version = "0.4", features = ["std"] }
|
log = { version = "0.4", features = ["std"] }
|
||||||
unicode_names2 = { version = "0.6.0", default-features = false }
|
unicode_names2 = { version = "0.6.0", default-features = false }
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ impl super::View for ContextMenus {
|
|||||||
|
|
||||||
impl ContextMenus {
|
impl ContextMenus {
|
||||||
fn example_plot(&self, ui: &mut egui::Ui) -> egui::Response {
|
fn example_plot(&self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
use egui::plot::{Line, PlotPoints};
|
use egui_plot::{Line, PlotPoints};
|
||||||
let n = 128;
|
let n = 128;
|
||||||
let line = Line::new(
|
let line = Line::new(
|
||||||
(0..=n)
|
(0..=n)
|
||||||
@@ -137,7 +137,7 @@ impl ContextMenus {
|
|||||||
})
|
})
|
||||||
.collect::<PlotPoints>(),
|
.collect::<PlotPoints>(),
|
||||||
);
|
);
|
||||||
egui::plot::Plot::new("example_plot")
|
egui_plot::Plot::new("example_plot")
|
||||||
.show_axes(self.show_axes)
|
.show_axes(self.show_axes)
|
||||||
.allow_drag(self.allow_drag)
|
.allow_drag(self.allow_drag)
|
||||||
.allow_zoom(self.allow_zoom)
|
.allow_zoom(self.allow_zoom)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::ops::RangeInclusive;
|
|||||||
|
|
||||||
use egui::*;
|
use egui::*;
|
||||||
|
|
||||||
use egui::plot::{
|
use egui_plot::{
|
||||||
Arrows, AxisBools, AxisHints, Bar, BarChart, BoxElem, BoxPlot, BoxSpread, CoordinatesFormatter,
|
Arrows, AxisBools, AxisHints, Bar, BarChart, BoxElem, BoxPlot, BoxSpread, CoordinatesFormatter,
|
||||||
Corner, GridInput, GridMark, HLine, Legend, Line, LineStyle, MarkerShape, Plot, PlotImage,
|
Corner, GridInput, GridMark, HLine, Legend, Line, LineStyle, MarkerShape, Plot, PlotImage,
|
||||||
PlotPoint, PlotPoints, PlotResponse, Points, Polygon, Text, VLine,
|
PlotPoint, PlotPoints, PlotResponse, Points, Polygon, Text, VLine,
|
||||||
@@ -575,7 +575,7 @@ impl CustomAxesDemo {
|
|||||||
.max_digits(4),
|
.max_digits(4),
|
||||||
AxisHints::default()
|
AxisHints::default()
|
||||||
.label("Absolute")
|
.label("Absolute")
|
||||||
.placement(plot::HPlacement::Right),
|
.placement(egui_plot::HPlacement::Right),
|
||||||
];
|
];
|
||||||
Plot::new("custom_axes")
|
Plot::new("custom_axes")
|
||||||
.data_aspect(2.0 * MINS_PER_DAY as f32)
|
.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(0.5));
|
||||||
plot_ui.line(LinkedAxesDemo::line_with_slope(1.0));
|
plot_ui.line(LinkedAxesDemo::line_with_slope(1.0));
|
||||||
plot_ui.line(LinkedAxesDemo::line_with_slope(2.0));
|
plot_ui.line(LinkedAxesDemo::line_with_slope(2.0));
|
||||||
@@ -671,7 +671,7 @@ impl LinkedAxesDemo {
|
|||||||
.height(250.0)
|
.height(250.0)
|
||||||
.y_axis_width(3)
|
.y_axis_width(3)
|
||||||
.y_axis_label("y")
|
.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_axis(link_group_id, self.link_x, self.link_y)
|
||||||
.link_cursor(link_group_id, self.link_cursor_x, self.link_cursor_y)
|
.link_cursor(link_group_id, self.link_cursor_x, self.link_cursor_y)
|
||||||
.show(ui, LinkedAxesDemo::configure_plot);
|
.show(ui, LinkedAxesDemo::configure_plot);
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ impl WidgetGallery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn example_plot(ui: &mut egui::Ui) -> egui::Response {
|
fn example_plot(ui: &mut egui::Ui) -> egui::Response {
|
||||||
use egui::plot::{Line, PlotPoints};
|
use egui_plot::{Line, PlotPoints};
|
||||||
let n = 128;
|
let n = 128;
|
||||||
let line_points: PlotPoints = (0..=n)
|
let line_points: PlotPoints = (0..=n)
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
@@ -268,7 +268,7 @@ fn example_plot(ui: &mut egui::Ui) -> egui::Response {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let line = Line::new(line_points);
|
let line = Line::new(line_points);
|
||||||
egui::plot::Plot::new("example_plot")
|
egui_plot::Plot::new("example_plot")
|
||||||
.height(32.0)
|
.height(32.0)
|
||||||
.show_axes(false)
|
.show_axes(false)
|
||||||
.data_aspect(1.0)
|
.data_aspect(1.0)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ fn month_data(year: i32, month: u32) -> Vec<Week> {
|
|||||||
if start.weekday() == Weekday::Sun {
|
if start.weekday() == Weekday::Sun {
|
||||||
weeks.push(Week {
|
weeks.push(Week {
|
||||||
number: start.iso_week().week() as u8,
|
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();
|
start = start.checked_add_signed(Duration::days(1)).unwrap();
|
||||||
|
|||||||
5
crates/egui_plot/CHANGELOG.md
Normal file
5
crates/egui_plot/CHANGELOG.md
Normal 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.
|
||||||
42
crates/egui_plot/Cargo.toml
Normal file
42
crates/egui_plot/Cargo.toml
Normal 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"] }
|
||||||
9
crates/egui_plot/README.md
Normal file
9
crates/egui_plot/README.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# egui_plot
|
||||||
|
|
||||||
|
[](https://crates.io/crates/egui_plot)
|
||||||
|
[](https://docs.rs/egui_plot)
|
||||||
|
[](https://github.com/rust-secure-code/safety-dance/)
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
Immediate mode plotting for [`egui`](https://github.com/emilk/egui).
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
use std::{fmt::Debug, ops::RangeInclusive, sync::Arc};
|
use std::{fmt::Debug, ops::RangeInclusive, sync::Arc};
|
||||||
|
|
||||||
use epaint::{
|
use egui::emath::{remap_clamp, round_to_decimals, Pos2, Rect};
|
||||||
emath::{remap_clamp, round_to_decimals},
|
use egui::epaint::{Shape, Stroke, TextShape};
|
||||||
Pos2, Rect, Shape, Stroke, TextShape,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{Response, Sense, TextStyle, Ui, WidgetText};
|
use crate::{Response, Sense, TextStyle, Ui, WidgetText};
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::emath::NumExt;
|
use egui::emath::NumExt;
|
||||||
use crate::epaint::{Color32, RectShape, Rounding, Shape, Stroke};
|
use egui::epaint::{Color32, RectShape, Rounding, Shape, Stroke};
|
||||||
|
|
||||||
use super::{add_rulers_and_text, highlighted_color, Orientation, PlotConfig, RectElement};
|
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.
|
/// One bar in a [`BarChart`]. Potentially floating, allowing stacked bar charts.
|
||||||
/// Width can be changed to allow variable-width histograms.
|
/// Width can be changed to allow variable-width histograms.
|
||||||
@@ -185,6 +185,6 @@ impl RectElement for Bar {
|
|||||||
Orientation::Vertical => scale[1],
|
Orientation::Vertical => scale[1],
|
||||||
};
|
};
|
||||||
let decimals = ((-scale.abs().log10()).ceil().at_least(0.0) as usize).at_most(6);
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
use crate::emath::NumExt;
|
use egui::emath::NumExt as _;
|
||||||
use crate::epaint::{Color32, RectShape, Rounding, Shape, Stroke};
|
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 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.
|
/// Contains the values of a single box in a box plot.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
use epaint::util::FloatOrd;
|
use epaint::{emath::Rot2, util::FloatOrd, Mesh};
|
||||||
use epaint::Mesh;
|
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
@@ -188,10 +187,10 @@ impl PlotItem for HLine {
|
|||||||
|
|
||||||
// Round to minimize aliasing:
|
// Round to minimize aliasing:
|
||||||
let points = vec![
|
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)),
|
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)),
|
transform.position_from_point(&PlotPoint::new(transform.bounds().max[0], *y)),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -304,10 +303,10 @@ impl PlotItem for VLine {
|
|||||||
|
|
||||||
// Round to minimize aliasing:
|
// Round to minimize aliasing:
|
||||||
let points = vec![
|
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])),
|
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])),
|
transform.position_from_point(&PlotPoint::new(*x, transform.bounds().max[1])),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -517,7 +516,7 @@ pub struct Polygon {
|
|||||||
pub(super) stroke: Stroke,
|
pub(super) stroke: Stroke,
|
||||||
pub(super) name: String,
|
pub(super) name: String,
|
||||||
pub(super) highlight: bool,
|
pub(super) highlight: bool,
|
||||||
pub(super) fill_alpha: f32,
|
pub(super) fill_color: Option<Color32>,
|
||||||
pub(super) style: LineStyle,
|
pub(super) style: LineStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,7 +527,7 @@ impl Polygon {
|
|||||||
stroke: Stroke::new(1.0, Color32::TRANSPARENT),
|
stroke: Stroke::new(1.0, Color32::TRANSPARENT),
|
||||||
name: Default::default(),
|
name: Default::default(),
|
||||||
highlight: false,
|
highlight: false,
|
||||||
fill_alpha: DEFAULT_FILL_ALPHA,
|
fill_color: None,
|
||||||
style: LineStyle::Solid,
|
style: LineStyle::Solid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,15 +551,21 @@ impl Polygon {
|
|||||||
self
|
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 {
|
pub fn color(mut self, color: impl Into<Color32>) -> Self {
|
||||||
self.stroke.color = color.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alpha of the filled area.
|
#[deprecated = "Use `fill_color`."]
|
||||||
pub fn fill_alpha(mut self, alpha: impl Into<f32>) -> Self {
|
#[allow(unused, clippy::needless_pass_by_value)]
|
||||||
self.fill_alpha = alpha.into();
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,24 +594,20 @@ impl PlotItem for Polygon {
|
|||||||
series,
|
series,
|
||||||
stroke,
|
stroke,
|
||||||
highlight,
|
highlight,
|
||||||
mut fill_alpha,
|
fill_color,
|
||||||
style,
|
style,
|
||||||
..
|
..
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
if *highlight {
|
|
||||||
fill_alpha = (2.0 * fill_alpha).at_most(1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut values_tf: Vec<_> = series
|
let mut values_tf: Vec<_> = series
|
||||||
.points()
|
.points()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| transform.position_from_point(v))
|
.map(|v| transform.position_from_point(v))
|
||||||
.collect();
|
.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);
|
shapes.push(shape);
|
||||||
values_tf.push(*values_tf.first().unwrap());
|
values_tf.push(*values_tf.first().unwrap());
|
||||||
style.style_line(values_tf, *stroke, *highlight, shapes);
|
style.style_line(values_tf, *stroke, *highlight, shapes);
|
||||||
@@ -1135,11 +1136,11 @@ pub struct PlotImage {
|
|||||||
pub(super) texture_id: TextureId,
|
pub(super) texture_id: TextureId,
|
||||||
pub(super) uv: Rect,
|
pub(super) uv: Rect,
|
||||||
pub(super) size: Vec2,
|
pub(super) size: Vec2,
|
||||||
|
pub(crate) rotation: f64,
|
||||||
pub(super) bg_fill: Color32,
|
pub(super) bg_fill: Color32,
|
||||||
pub(super) tint: Color32,
|
pub(super) tint: Color32,
|
||||||
pub(super) highlight: bool,
|
pub(super) highlight: bool,
|
||||||
pub(super) name: String,
|
pub(super) name: String,
|
||||||
pub(crate) rotation: Option<(f32, Vec2)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlotImage {
|
impl PlotImage {
|
||||||
@@ -1156,9 +1157,9 @@ impl PlotImage {
|
|||||||
texture_id: texture_id.into(),
|
texture_id: texture_id.into(),
|
||||||
uv: Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
|
uv: Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
|
rotation: 0.0,
|
||||||
bg_fill: Default::default(),
|
bg_fill: Default::default(),
|
||||||
tint: Color32::WHITE,
|
tint: Color32::WHITE,
|
||||||
rotation: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1198,14 +1199,9 @@ impl PlotImage {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rotate the image about an origin by some angle
|
/// Rotate the image counter-clockwise around its center by an angle in radians.
|
||||||
///
|
pub fn rotate(mut self, angle: f64) -> Self {
|
||||||
/// Positive angle is clockwise.
|
self.rotation = angle;
|
||||||
/// 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));
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1214,6 +1210,7 @@ impl PlotItem for PlotImage {
|
|||||||
fn shapes(&self, ui: &mut Ui, transform: &PlotTransform, shapes: &mut Vec<Shape>) {
|
fn shapes(&self, ui: &mut Ui, transform: &PlotTransform, shapes: &mut Vec<Shape>) {
|
||||||
let Self {
|
let Self {
|
||||||
position,
|
position,
|
||||||
|
rotation,
|
||||||
texture_id,
|
texture_id,
|
||||||
uv,
|
uv,
|
||||||
size,
|
size,
|
||||||
@@ -1222,31 +1219,40 @@ impl PlotItem for PlotImage {
|
|||||||
highlight,
|
highlight,
|
||||||
..
|
..
|
||||||
} = self;
|
} = self;
|
||||||
let rect = {
|
let image_screen_rect = {
|
||||||
let left_top = PlotPoint::new(
|
let left_top = PlotPoint::new(
|
||||||
position.x as f32 - size.x / 2.0,
|
position.x - 0.5 * size.x as f64,
|
||||||
position.y as f32 - size.y / 2.0,
|
position.y - 0.5 * size.y as f64,
|
||||||
);
|
);
|
||||||
let right_bottom = PlotPoint::new(
|
let right_bottom = PlotPoint::new(
|
||||||
position.x as f32 + size.x / 2.0,
|
position.x + 0.5 * size.x as f64,
|
||||||
position.y as f32 + size.y / 2.0,
|
position.y + 0.5 * size.y as f64,
|
||||||
);
|
);
|
||||||
let left_top_tf = transform.position_from_point(&left_top);
|
let left_top_screen = transform.position_from_point(&left_top);
|
||||||
let right_bottom_tf = transform.position_from_point(&right_bottom);
|
let right_bottom_screen = transform.position_from_point(&right_bottom);
|
||||||
Rect::from_two_pos(left_top_tf, right_bottom_tf)
|
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)
|
.bg_fill(*bg_fill)
|
||||||
.tint(*tint)
|
.tint(*tint)
|
||||||
.uv(*uv);
|
.uv(*uv)
|
||||||
if let Some((angle, origin)) = self.rotation {
|
.rotate(screen_rotation, Vec2::splat(0.5))
|
||||||
image = image.rotate(angle, origin);
|
.paint_at(ui, image_screen_rect);
|
||||||
}
|
|
||||||
image.paint_at(ui, rect);
|
|
||||||
if *highlight {
|
if *highlight {
|
||||||
shapes.push(Shape::rect_stroke(
|
let center = image_screen_rect.center();
|
||||||
rect,
|
let rotation = Rot2::from_angle(screen_rotation);
|
||||||
0.0,
|
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()),
|
Stroke::new(1.0, ui.visuals().strong_text_color()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -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 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
|
/// Trait that abstracts from rectangular 'Value'-like elements, such as bars or boxes
|
||||||
pub(super) trait RectElement {
|
pub(super) trait RectElement {
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use epaint::{Pos2, Shape, Stroke, Vec2};
|
|
||||||
use std::ops::{Bound, RangeBounds, RangeInclusive};
|
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.
|
/// A point coordinate in the plot.
|
||||||
///
|
///
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
//! Simple plotting library.
|
//! Simple plotting library.
|
||||||
|
//!
|
||||||
|
//! ## Feature flags
|
||||||
|
#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
|
||||||
|
//!
|
||||||
|
|
||||||
use std::{ops::RangeInclusive, sync::Arc};
|
use std::{ops::RangeInclusive, sync::Arc};
|
||||||
|
|
||||||
use ahash::HashMap;
|
use egui::ahash::HashMap;
|
||||||
use epaint::util::FloatOrd;
|
use epaint::util::FloatOrd;
|
||||||
use epaint::Hsva;
|
use epaint::Hsva;
|
||||||
|
|
||||||
@@ -10,7 +14,7 @@ use axis::AxisWidget;
|
|||||||
use items::PlotItem;
|
use items::PlotItem;
|
||||||
use legend::LegendWidget;
|
use legend::LegendWidget;
|
||||||
|
|
||||||
use crate::*;
|
use egui::*;
|
||||||
|
|
||||||
pub use items::{
|
pub use items::{
|
||||||
Arrows, Bar, BarChart, BoxElem, BoxPlot, BoxSpread, HLine, Line, LineStyle, MarkerShape,
|
Arrows, Bar, BarChart, BoxElem, BoxPlot, BoxSpread, HLine, Line, LineStyle, MarkerShape,
|
||||||
@@ -182,7 +186,7 @@ pub struct PlotResponse<R> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # egui::__run_test_ui(|ui| {
|
/// # 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 sin: PlotPoints = (0..1000).map(|i| {
|
||||||
/// let x = i as f64 * 0.01;
|
/// let x = i as f64 * 0.01;
|
||||||
/// [x, x.sin()]
|
/// [x, x.sin()]
|
||||||
@@ -394,7 +398,7 @@ impl Plot {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # egui::__run_test_ui(|ui| {
|
/// # 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 sin: PlotPoints = (0..1000).map(|i| {
|
||||||
/// let x = i as f64 * 0.01;
|
/// let x = i as f64 * 0.01;
|
||||||
/// [x, x.sin()]
|
/// [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
|
/// 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:
|
/// 100 and small ones at 25, you can return:
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use egui::plot::GridMark;
|
/// # use egui_plot::GridMark;
|
||||||
/// vec![
|
/// vec![
|
||||||
/// // 100s
|
/// // 100s
|
||||||
/// GridMark { value: 100.0, step_size: 100.0 },
|
/// GridMark { value: 100.0, step_size: 100.0 },
|
||||||
@@ -1781,8 +1785,8 @@ impl PreparedPlot {
|
|||||||
|
|
||||||
if self.sharp_grid_lines {
|
if self.sharp_grid_lines {
|
||||||
// Round to avoid aliasing
|
// Round to avoid aliasing
|
||||||
p0 = ui.ctx().round_pos_to_pixels(p0);
|
p0 = ui.painter().round_pos_to_pixels(p0);
|
||||||
p1 = ui.ctx().round_pos_to_pixels(p1);
|
p1 = ui.painter().round_pos_to_pixels(p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
shapes.push((
|
shapes.push((
|
||||||
@@ -1851,7 +1855,7 @@ impl PreparedPlot {
|
|||||||
/// Returns next bigger power in given base
|
/// Returns next bigger power in given base
|
||||||
/// e.g.
|
/// e.g.
|
||||||
/// ```ignore
|
/// ```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.01, 10.0), 0.01);
|
||||||
/// assert_eq!(next_power(0.02, 10.0), 0.1);
|
/// assert_eq!(next_power(0.02, 10.0), 0.1);
|
||||||
/// assert_eq!(next_power(0.2, 10.0), 1);
|
/// assert_eq!(next_power(0.2, 10.0), 1);
|
||||||
@@ -24,6 +24,7 @@ default = []
|
|||||||
|
|
||||||
## Enable additional checks if debug assertions are enabled (debug builds).
|
## Enable additional checks if debug assertions are enabled (debug builds).
|
||||||
extra_debug_asserts = []
|
extra_debug_asserts = []
|
||||||
|
|
||||||
## Always enable additional checks.
|
## Always enable additional checks.
|
||||||
extra_asserts = []
|
extra_asserts = []
|
||||||
|
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ impl TexturesDelta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, mut newer: 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);
|
self.free.append(&mut newer.free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ unmaintained = "warn"
|
|||||||
yanked = "deny"
|
yanked = "deny"
|
||||||
ignore = [
|
ignore = [
|
||||||
"RUSTSEC-2020-0071", # https://rustsec.org/advisories/RUSTSEC-2020-0071 - chrono/time: Potential segfault in the time crate
|
"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]
|
[bans]
|
||||||
|
|||||||
@@ -62,10 +62,18 @@ impl eframe::App for MyApp {
|
|||||||
} else {
|
} else {
|
||||||
"???".to_owned()
|
"???".to_owned()
|
||||||
};
|
};
|
||||||
if let Some(bytes) = &file.bytes {
|
|
||||||
use std::fmt::Write as _;
|
let mut additional_info = vec![];
|
||||||
write!(info, " ({} bytes)", bytes.len()).ok();
|
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);
|
ui.label(info);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ publish = false
|
|||||||
eframe = { path = "../../crates/eframe", features = [
|
eframe = { path = "../../crates/eframe", features = [
|
||||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
"__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"] }
|
image = { version = "0.24", default-features = false, features = ["png"] }
|
||||||
rfd = "0.11.0"
|
rfd = "0.11.0"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
#![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::ColorImage;
|
||||||
use eframe::egui::{self, ViewportRender};
|
use eframe::egui::{self, ViewportRender};
|
||||||
|
use egui_plot::{Legend, Line, Plot, PlotPoints};
|
||||||
|
|
||||||
fn main() -> Result<(), eframe::Error> {
|
fn main() -> Result<(), eframe::Error> {
|
||||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ def main() -> None:
|
|||||||
"ecolor",
|
"ecolor",
|
||||||
"eframe",
|
"eframe",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
|
"egui_plot",
|
||||||
"egui_glow",
|
"egui_glow",
|
||||||
"egui-wgpu",
|
"egui-wgpu",
|
||||||
"egui-winit",
|
"egui-winit",
|
||||||
@@ -141,8 +142,6 @@ def main() -> None:
|
|||||||
unsorted_prs = []
|
unsorted_prs = []
|
||||||
unsorted_commits = []
|
unsorted_commits = []
|
||||||
|
|
||||||
plot = []
|
|
||||||
|
|
||||||
for commit_info, pr_info in zip(commit_infos, pr_infos):
|
for commit_info, pr_info in zip(commit_infos, pr_infos):
|
||||||
hexsha = commit_info.hexsha
|
hexsha = commit_info.hexsha
|
||||||
title = commit_info.title
|
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.
|
continue # We get so many typo PRs. Let's not flood the changelog with them.
|
||||||
|
|
||||||
added = False
|
added = False
|
||||||
if 'plot' in labels:
|
|
||||||
plot.append(summary)
|
for crate in crate_names:
|
||||||
added = True
|
if crate in labels:
|
||||||
else:
|
sections.setdefault(crate, []).append(summary)
|
||||||
for crate in crate_names:
|
added = True
|
||||||
if crate in labels:
|
|
||||||
sections.setdefault(crate, []).append(summary)
|
|
||||||
added = True
|
|
||||||
|
|
||||||
if not added:
|
if not added:
|
||||||
if not any(label in labels for label in ignore_labels):
|
if not any(label in labels for label in ignore_labels):
|
||||||
@@ -188,9 +184,6 @@ def main() -> None:
|
|||||||
if crate in sections:
|
if crate in sections:
|
||||||
summary = sections[crate]
|
summary = sections[crate]
|
||||||
print_section(crate, summary)
|
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 PRs", unsorted_prs)
|
||||||
print_section("Unsorted commits", unsorted_commits)
|
print_section("Unsorted commits", unsorted_commits)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user