diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 107f9b18..afab15a0 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -4,7 +4,7 @@ on: branches: - "main" pull_request: - types: [ opened, synchronize ] + types: [opened, synchronize] name: Rust @@ -22,7 +22,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: default - toolchain: 1.88.0 + toolchain: 1.92.0 override: true - name: Install packages (Linux) @@ -70,7 +70,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.88.0 + toolchain: 1.92.0 target: wasm32-unknown-unknown override: true components: clippy @@ -95,7 +95,7 @@ jobs: - uses: actions/checkout@v3 - uses: EmbarkStudios/cargo-deny-action@v2 with: - rust-version: "1.88.0" + rust-version: "1.92.0" log-level: warn command: check @@ -109,7 +109,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.88.0 + toolchain: 1.92.0 target: wasm32-unknown-unknown override: true - name: Download and install Trunk binary @@ -131,7 +131,7 @@ jobs: lfs: true - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.88.0 + toolchain: 1.92.0 - name: Set up cargo cache uses: Swatinem/rust-cache@v2 diff --git a/Cargo.toml b/Cargo.toml index 1de2bcf9..09f72d75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ members = ["egui_plot", "demo", "examples/*", "examples_utils"] [workspace.package] edition = "2024" license = "MIT OR Apache-2.0" -rust-version = "1.88" +rust-version = "1.92" version = "0.34.1" @@ -102,26 +102,33 @@ missing_crate_level_docs = "warn" # See also clippy.toml [workspace.lints.clippy] +all = { level = "warn", priority = -1 } + allow_attributes = "warn" -allow_attributes_without_reason = "warn" as_ptr_cast_mut = "warn" await_holding_lock = "warn" bool_to_int_with_if = "warn" branches_sharing_code = "warn" +cast_possible_wrap = "warn" char_lit_as_u8 = "warn" checked_conversions = "warn" clear_with_drain = "warn" +clone_on_ref_ptr = "warn" cloned_instead_of_copied = "warn" +coerce_container_to_any = "warn" +comparison_chain = "warn" dbg_macro = "warn" debug_assert_with_mut_call = "warn" default_union_representation = "warn" derive_partial_eq_without_eq = "warn" -disallowed_macros = "warn" # See clippy.toml -disallowed_methods = "warn" # See clippy.toml -disallowed_names = "warn" # See clippy.toml -disallowed_script_idents = "warn" # See clippy.toml -disallowed_types = "warn" # See clippy.toml +disallowed_macros = "warn" # See clippy.toml +disallowed_methods = "warn" # See clippy.toml +disallowed_names = "warn" # See clippy.toml +disallowed_script_idents = "warn" # See clippy.toml +disallowed_types = "warn" # See clippy.toml +doc_broken_link = "warn" doc_comment_double_space_linebreaks = "warn" +doc_include_without_cfg = "warn" doc_link_with_quotes = "warn" doc_markdown = "warn" elidable_lifetime_names = "warn" @@ -155,6 +162,7 @@ inefficient_to_string = "warn" infinite_loop = "warn" into_iter_without_iter = "warn" invalid_upcast_comparisons = "warn" +ip_constant = "warn" iter_filter_is_ok = "warn" iter_filter_is_some = "warn" iter_not_returning_iterator = "warn" @@ -163,6 +171,7 @@ iter_on_single_items = "warn" iter_over_hash_type = "warn" iter_without_into_iter = "warn" large_digit_groups = "warn" +large_futures = "warn" large_include_file = "warn" large_stack_arrays = "warn" large_stack_frames = "warn" @@ -228,6 +237,7 @@ ref_patterns = "warn" rest_pat_in_fully_bound_structs = "warn" return_and_then = "warn" same_functions_in_if_condition = "warn" +self_only_used_in_recursion = "warn" semicolon_if_nothing_returned = "warn" set_contains_or_insert = "warn" should_panic_without_expect = "warn" @@ -240,7 +250,6 @@ string_add = "warn" string_add_assign = "warn" string_lit_as_bytes = "warn" string_lit_chars_any = "warn" -string_to_string = "warn" suspicious_command_arg_space = "warn" suspicious_xor_used_as_pow = "warn" todo = "warn" @@ -250,7 +259,7 @@ trailing_empty_array = "warn" trait_duplication_in_bounds = "warn" transmute_ptr_to_ptr = "warn" tuple_array_conversions = "warn" -unchecked_duration_subtraction = "warn" +unchecked_time_subtraction = "warn" undocumented_unsafe_blocks = "warn" unimplemented = "warn" uninhabited_references = "warn" @@ -265,6 +274,7 @@ unnecessary_semicolon = "warn" unnecessary_struct_initialization = "warn" unnecessary_wraps = "warn" unnested_or_patterns = "warn" +unused_async = "warn" unused_peekable = "warn" unused_rounding = "warn" unused_self = "warn" @@ -278,8 +288,11 @@ wildcard_dependencies = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" -manual_range_contains = "allow" # this is better on 'allow' -map_unwrap_or = "allow" # this is better on 'allow' +assigning_clones = "allow" # No please +manual_range_contains = "allow" # this one is just worse imho +map_unwrap_or = "allow" # so is this one +self_named_module_files = "allow" # Disabled waiting on https://github.com/rust-lang/rust-clippy/issues/9602 +significant_drop_tightening = "allow" # Too many false positives [workspace.metadata.cargo-shear] diff --git a/clippy.toml b/clippy.toml index 1c5455d0..9f217cc4 100644 --- a/clippy.toml +++ b/clippy.toml @@ -5,7 +5,7 @@ # ----------------------------------------------------------------------------- # Section identical to scripts/clippy_wasm/clippy.toml: -msrv = "1.88" +msrv = "1.92" allow-unwrap-in-tests = true diff --git a/demo/src/app.rs b/demo/src/app.rs index 8a2d1038..da605d95 100644 --- a/demo/src/app.rs +++ b/demo/src/app.rs @@ -67,10 +67,8 @@ impl DemoGallery { let is_small_screen = screen_rect.width() < 1024.0; Self::top_bar(ctx); - if !is_small_screen { - if let Some(index) = self.current_example { - self.info_panel(ctx, index); - } + if !is_small_screen && let Some(index) = self.current_example { + self.info_panel(ctx, index); } self.thumbnails_panel(ctx, screen_rect.width() / 3.0); self.demo_panel(ctx); diff --git a/egui_plot/src/aesthetics.rs b/egui_plot/src/aesthetics.rs index 31cb647f..c84d2eea 100644 --- a/egui_plot/src/aesthetics.rs +++ b/egui_plot/src/aesthetics.rs @@ -92,18 +92,13 @@ impl std::fmt::Display for LineStyle { } /// Determines whether a plot element is vertically or horizontally oriented. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] pub enum Orientation { Horizontal, + #[default] Vertical, } -impl Default for Orientation { - fn default() -> Self { - Self::Vertical - } -} - /// Circle, Diamond, Square, Cross, … #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum MarkerShape { diff --git a/egui_plot/src/grid.rs b/egui_plot/src/grid.rs index 509c7545..e6334d64 100644 --- a/egui_plot/src/grid.rs +++ b/egui_plot/src/grid.rs @@ -119,14 +119,14 @@ fn generate_marks(step_sizes: [f64; 3], bounds: (f64, f64)) -> Vec { let mut deduplicated: Vec = Vec::with_capacity(steps.len()); for step in steps { - if let Some(last) = deduplicated.last_mut() { - if (last.value - step.value).abs() < eps { - // Keep the one with the largest step size - if last.step_size < step.step_size { - *last = step; - } - continue; + if let Some(last) = deduplicated.last_mut() + && (last.value - step.value).abs() < eps + { + // Keep the one with the largest step size + if last.step_size < step.step_size { + *last = step; } + continue; } deduplicated.push(step); } diff --git a/egui_plot/src/items/bar_chart.rs b/egui_plot/src/items/bar_chart.rs index 64944961..16685233 100644 --- a/egui_plot/src/items/bar_chart.rs +++ b/egui_plot/src/items/bar_chart.rs @@ -35,7 +35,7 @@ pub struct BarChart { default_color: Color32, /// A custom element formatter - pub(crate) element_formatter: Option String>>, + pub(crate) element_formatter: Option String>>, } impl BarChart { diff --git a/egui_plot/src/items/box_plot.rs b/egui_plot/src/items/box_plot.rs index 6bb416b7..74c3238d 100644 --- a/egui_plot/src/items/box_plot.rs +++ b/egui_plot/src/items/box_plot.rs @@ -34,7 +34,7 @@ pub struct BoxPlot { default_color: Color32, /// A custom element formatter - pub(crate) element_formatter: Option String>>, + pub(crate) element_formatter: Option String>>, } impl BoxPlot { diff --git a/egui_plot/src/items/heatmap.rs b/egui_plot/src/items/heatmap.rs index 2e72548b..ed8d1428 100644 --- a/egui_plot/src/items/heatmap.rs +++ b/egui_plot/src/items/heatmap.rs @@ -1,4 +1,5 @@ use std::ops::RangeInclusive; +use std::sync::Arc; use egui::Color32; use egui::Mesh; @@ -117,7 +118,7 @@ impl Heatmap { /// `values.len()` is not divisible by `cols`), an empty heatmap is created. pub fn new(values: Vec, cols: usize) -> Self { // Handle invalid parameters by creating an empty heatmap - if cols == 0 || values.is_empty() || (values.len() % cols) != 0 { + if cols == 0 || values.is_empty() || !values.len().is_multiple_of(cols) { return Self::empty(); } @@ -329,10 +330,8 @@ impl Heatmap { fn tile_view_info(&self, ui: &Ui, transform: &PlotTransform, index: usize) -> (Rect, Color32, Shape) { let v = self.values[index]; - // calculate color value - let mut fill_color: Color32; - if let Some(mapping) = &self.custom_mapping { - fill_color = mapping(v); + let mut fill_color = if let Some(mapping) = &self.custom_mapping { + mapping(v) } else { // convert to value in [0.0, 1.0] let v_rel = (v - self.min) / (self.max - self.min); @@ -340,8 +339,8 @@ impl Heatmap { // convert to color palette index let palette_index = (v_rel * (self.palette.len() - 1) as f64).round() as usize; - fill_color = self.palette[palette_index]; - } + self.palette[palette_index] + }; if self.highlight { let fill = Rgba::from(fill_color); @@ -385,7 +384,7 @@ impl Heatmap { ); let text_pos = tile_rect.center() - galley.size() / 2.0; - let text = Shape::galley(text_pos, galley.clone(), Color32::WHITE); + let text = Shape::galley(text_pos, Arc::clone(&galley), Color32::WHITE); (tile_rect, fill_color, text) } } diff --git a/egui_plot/src/items/series.rs b/egui_plot/src/items/series.rs index 95ade02e..230dd306 100644 --- a/egui_plot/src/items/series.rs +++ b/egui_plot/src/items/series.rs @@ -169,17 +169,18 @@ impl PlotItem for Line<'_> { } = self; let mut fill = *fill; - let mut final_stroke: PathStroke = (*stroke).into(); - // if we have a gradient color, we need to wrap the stroke callback to transpose - // the position to a value the caller can reason about - if let Some(gradient_callback) = self.gradient_color.clone() { + let final_stroke: PathStroke = if let Some(gradient_callback) = self.gradient_color.clone() { + // if we have a gradient color, we need to wrap the stroke callback to transpose + // the position to a value the caller can reason about let local_transform = *transform; let wrapped_callback = move |_rec: Rect, pos: Pos2| -> Color32 { let point = local_transform.value_from_position(pos); gradient_callback(point) }; - final_stroke = PathStroke::new_uv(stroke.width, wrapped_callback.clone()); - } + PathStroke::new_uv(stroke.width, wrapped_callback.clone()) + } else { + (*stroke).into() + }; let values_tf: Vec<_> = series .points() diff --git a/egui_plot/src/overlays/legend.rs b/egui_plot/src/overlays/legend.rs index dba053d6..f0da5975 100644 --- a/egui_plot/src/overlays/legend.rs +++ b/egui_plot/src/overlays/legend.rs @@ -335,10 +335,10 @@ impl Widget for &mut LegendWidget { background_frame .show(ui, |ui| { // always show on top of the legend - so we need to use a new scope - if main_dir == Direction::TopDown { - if let Some(title) = &config.title { - ui.heading(title); - } + if main_dir == Direction::TopDown + && let Some(title) = &config.title + { + ui.heading(title); } let mut focus_on_item = None; @@ -363,10 +363,10 @@ impl Widget for &mut LegendWidget { .reduce(|r1, r2| r1.union(r2)) .expect("No entries in the legend"); - if main_dir == Direction::BottomUp { - if let Some(title) = &config.title { - ui.heading(title); - } + if main_dir == Direction::BottomUp + && let Some(title) = &config.title + { + ui.heading(title); } if let Some(focus_on_item) = focus_on_item { diff --git a/egui_plot/src/plot.rs b/egui_plot/src/plot.rs index 1623cce8..86a8d891 100644 --- a/egui_plot/src/plot.rs +++ b/egui_plot/src/plot.rs @@ -1127,29 +1127,28 @@ impl<'a> Plot<'a> { // Drag axes to zoom: for d in 0..2 { - if self.allow_axis_zoom_drag[d] { - if let Some(axis_response) = axis_responses[d].iter().find(|r| r.dragged_by(PointerButton::Primary)) { - if let Some(drag_start_pos) = ui.input(|i| i.pointer.press_origin()) { - let delta = axis_response.drag_delta(); - - let axis_zoom = 1.0 + (0.02 * delta[d]).clamp(-1.0, 1.0); - - let zoom = if self.data_aspect.is_some() { - // Zoom both axes equally to maintain aspect ratio: - Vec2::splat(axis_zoom) - } else { - let mut zoom = Vec2::splat(1.0); - zoom[d] = axis_zoom; - zoom - }; - - if zoom != Vec2::splat(1.0) { - let mut zoom_center = plot_rect.center(); - zoom_center[d] = drag_start_pos[d]; - mem.transform.zoom(zoom, zoom_center); - mem.auto_bounds = false.into(); - } - } + if self.allow_axis_zoom_drag[d] + && let Some(axis_response) = axis_responses[d].iter().find(|r| r.dragged_by(PointerButton::Primary)) + && let Some(drag_start_pos) = ui.input(|i| i.pointer.press_origin()) + { + let delta = axis_response.drag_delta(); + + let axis_zoom = 1.0 + (0.02 * delta[d]).clamp(-1.0, 1.0); + + let zoom = if self.data_aspect.is_some() { + // Zoom both axes equally to maintain aspect ratio: + Vec2::splat(axis_zoom) + } else { + let mut zoom = Vec2::splat(1.0); + zoom[d] = axis_zoom; + zoom + }; + + if zoom != Vec2::splat(1.0) { + let mut zoom_center = plot_rect.center(); + zoom_center[d] = drag_start_pos[d]; + mem.transform.zoom(zoom, zoom_center); + mem.auto_bounds = false.into(); } } } @@ -1266,7 +1265,7 @@ impl<'a> Plot<'a> { for widget in &mut axis_widgets[0] { widget.range = x_axis_range.clone(); widget.transform = Some(mem.transform); - widget.steps = x_steps.clone(); + widget.steps = Arc::clone(&x_steps); } let x_axis_widgets = std::mem::take(&mut axis_widgets[0]); for (i, widget) in x_axis_widgets.into_iter().enumerate() { @@ -1278,7 +1277,7 @@ impl<'a> Plot<'a> { for widget in &mut axis_widgets[1] { widget.range = y_axis_range.clone(); widget.transform = Some(mem.transform); - widget.steps = y_steps.clone(); + widget.steps = Arc::clone(&y_steps); } let y_axis_widgets = std::mem::take(&mut axis_widgets[1]); for (i, widget) in y_axis_widgets.into_iter().enumerate() { @@ -1561,7 +1560,7 @@ impl<'a> Plot<'a> { let interact_radius_sq = ui.style().interaction.interact_radius.powi(2); - let candidates = plot_ui + let mut candidates = plot_ui .items .iter() .filter(|entry| entry.allow_hover()) @@ -1575,9 +1574,7 @@ impl<'a> Plot<'a> { // Since many items can have same distance, // and dist_sq can be zero for some items (e.g. rectangle) // we pick topmost item within interact radius - let topmost = candidates - .filter(|(_, elem)| elem.dist_sq <= interact_radius_sq) - .next_back(); + let topmost = candidates.rfind(|(_, elem)| elem.dist_sq <= interact_radius_sq); let plot = crate::PlotConfig { ui, diff --git a/examples/borrow_points/src/lib.rs b/examples/borrow_points/src/lib.rs index 45709263..b7af0fb0 100644 --- a/examples/borrow_points/src/lib.rs +++ b/examples/borrow_points/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/box_plot/src/lib.rs b/examples/box_plot/src/lib.rs index befaed4a..09e14c8c 100644 --- a/examples/box_plot/src/lib.rs +++ b/examples/box_plot/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/custom_axes/src/lib.rs b/examples/custom_axes/src/lib.rs index 41ddafea..d2887b1d 100644 --- a/examples/custom_axes/src/lib.rs +++ b/examples/custom_axes/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/custom_plot_manipulation/src/lib.rs b/examples/custom_plot_manipulation/src/lib.rs index e2316538..99e998cf 100644 --- a/examples/custom_plot_manipulation/src/lib.rs +++ b/examples/custom_plot_manipulation/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/filled_area/src/lib.rs b/examples/filled_area/src/lib.rs index a9594529..2e61e53d 100644 --- a/examples/filled_area/src/lib.rs +++ b/examples/filled_area/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/heatmap/src/lib.rs b/examples/heatmap/src/lib.rs index 564e285f..d825c0f0 100644 --- a/examples/heatmap/src/lib.rs +++ b/examples/heatmap/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/histogram/src/lib.rs b/examples/histogram/src/lib.rs index 0f21155d..e37ecf81 100644 --- a/examples/histogram/src/lib.rs +++ b/examples/histogram/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/interaction/src/lib.rs b/examples/interaction/src/lib.rs index 4cd5a9be..6460bc5d 100644 --- a/examples/interaction/src/lib.rs +++ b/examples/interaction/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/items/src/lib.rs b/examples/items/src/lib.rs index ae8d86e2..fe609253 100644 --- a/examples/items/src/lib.rs +++ b/examples/items/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/legend/src/lib.rs b/examples/legend/src/lib.rs index e652894e..ade9c2bd 100644 --- a/examples/legend/src/lib.rs +++ b/examples/legend/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/legend_sort/src/lib.rs b/examples/legend_sort/src/lib.rs index ebe48c30..cd79efed 100644 --- a/examples/legend_sort/src/lib.rs +++ b/examples/legend_sort/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/lines/src/lib.rs b/examples/lines/src/lib.rs index de4914af..c125c0d5 100644 --- a/examples/lines/src/lib.rs +++ b/examples/lines/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/linked_axes/src/lib.rs b/examples/linked_axes/src/lib.rs index 14e1a9f6..b6256540 100644 --- a/examples/linked_axes/src/lib.rs +++ b/examples/linked_axes/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/markers/src/lib.rs b/examples/markers/src/lib.rs index 59b24de7..e8ee8c03 100644 --- a/examples/markers/src/lib.rs +++ b/examples/markers/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/performance/src/lib.rs b/examples/performance/src/lib.rs index 5c4717c2..076bbd34 100644 --- a/examples/performance/src/lib.rs +++ b/examples/performance/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/plot_span/src/lib.rs b/examples/plot_span/src/lib.rs index 9d1d92d0..5c6f237c 100644 --- a/examples/plot_span/src/lib.rs +++ b/examples/plot_span/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/save_plot/src/app.rs b/examples/save_plot/src/app.rs index 6d5988ad..9afcef70 100644 --- a/examples/save_plot/src/app.rs +++ b/examples/save_plot/src/app.rs @@ -29,32 +29,32 @@ impl SavePlotExample { let screenshot = ctx.input(|i| { for event in &i.raw.events { if let egui::Event::Screenshot { image, .. } = event { - return Some(image.clone()); + return Some(std::sync::Arc::clone(image)); } } None }); - if let (Some(screenshot), Some(plot_location)) = (screenshot, self.plot_rect) { - if let Some(mut path) = rfd::FileDialog::new().save_file() { - path.set_extension("png"); + if let (Some(screenshot), Some(plot_location)) = (screenshot, self.plot_rect) + && let Some(mut path) = rfd::FileDialog::new().save_file() + { + path.set_extension("png"); - // for a full size application, we should put this in a different thread, - // so that the GUI doesn't lag during saving + // for a full size application, we should put this in a different thread, + // so that the GUI doesn't lag during saving - let pixels_per_point = ctx.pixels_per_point(); - let plot = screenshot.region(&plot_location, Some(pixels_per_point)); - // save the plot to png - let result = image::save_buffer( - &path, - plot.as_raw(), - plot.width() as u32, - plot.height() as u32, - image::ColorType::Rgba8, - ); - match result { - Ok(()) => eprintln!("Image saved to {}", path.display()), - Err(err) => eprintln!("Failed to save image to {}: {err}", path.display()), - } + let pixels_per_point = ctx.pixels_per_point(); + let plot = screenshot.region(&plot_location, Some(pixels_per_point)); + // save the plot to png + let result = image::save_buffer( + &path, + plot.as_raw(), + plot.width() as u32, + plot.height() as u32, + image::ColorType::Rgba8, + ); + match result { + Ok(()) => eprintln!("Image saved to {}", path.display()), + Err(err) => eprintln!("Failed to save image to {}: {err}", path.display()), } } } diff --git a/examples/save_plot/src/lib.rs b/examples/save_plot/src/lib.rs index 944da127..9d0d04d8 100644 --- a/examples/save_plot/src/lib.rs +++ b/examples/save_plot/src/lib.rs @@ -1,5 +1,5 @@ #![expect(clippy::print_stderr, reason = "example template")] -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/examples/stacked_bar/src/lib.rs b/examples/stacked_bar/src/lib.rs index bd1bb662..eb5fa62c 100644 --- a/examples/stacked_bar/src/lib.rs +++ b/examples/stacked_bar/src/lib.rs @@ -1,4 +1,4 @@ -#![doc = include_str!("../README.md")] +#![cfg_attr(doc, doc = include_str!("../README.md"))] use eframe::egui; use examples_utils::PlotExample; diff --git a/rust-toolchain b/rust-toolchain index 9d6f61e5..ce5b5098 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -5,6 +5,6 @@ # to the user in the error, instead of "error: invalid channel name '[toolchain]'". [toolchain] -channel = "1.88" # Avoid specifying a patch version here; see https://github.com/emilk/eframe_template/issues/145 +channel = "1.92.0" components = ["rustfmt", "clippy"] targets = ["wasm32-unknown-unknown"] diff --git a/scripts/check.sh b/scripts/check.sh index a873ecf8..620484c2 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -9,7 +9,7 @@ set -x # Checks all tests, lints etc. # Basically does what the CI does. -cargo +1.88 install --quiet typos-cli +cargo +1.92 install --quiet typos-cli export RUSTFLAGS="-D warnings" export RUSTDOCFLAGS="-D warnings" # https://github.com/emilk/egui/pull/1454 diff --git a/scripts/clippy_wasm/clippy.toml b/scripts/clippy_wasm/clippy.toml index c80aa311..919e997f 100644 --- a/scripts/clippy_wasm/clippy.toml +++ b/scripts/clippy_wasm/clippy.toml @@ -8,7 +8,7 @@ # ----------------------------------------------------------------------------- # Section identical to the main clippy.toml: -msrv = "1.88" +msrv = "1.92" allow-unwrap-in-tests = true