1313//! restrict the run to a single palette. Captures land at
1414//! `<PLOTX_SHOT>/<theme>/<scene>.png`.
1515
16- use std:: path:: { Path , PathBuf } ;
16+ use std:: path:: PathBuf ;
1717use std:: sync:: Arc ;
1818use std:: time:: { Duration , Instant } ;
1919
@@ -31,6 +31,7 @@ use plotx_io::xps::{
3131} ;
3232use plotx_io:: { AxisSource , Dim , Domain , NmrData , NmrData2D , PseudoAxis , PseudoKind , QuadMode } ;
3333
34+ mod capture;
3435mod craft_shot;
3536
3637const FIT_LO : f64 = 1.4 ;
@@ -88,6 +89,7 @@ enum Op {
8889 RegionResult ,
8990 /// Open the result's synchronized read-only values.
9091 RegionData ,
92+ History ( bool ) ,
9193 XpsSetup ,
9294 CraftSetup ,
9395 XpsTab ( plotx_core:: state:: XpsWorkbenchTab ) ,
@@ -136,6 +138,9 @@ const SCENES: &[Scene] = &[
136138 act ( 2 , Op :: Zoom ( 0.75 ) ) ,
137139 act ( 2 , Op :: Setup ) ,
138140 shot ( 8 , "band" ) ,
141+ act ( 2 , Op :: History ( true ) ) ,
142+ shot ( 8 , "operation_history" ) ,
143+ act ( 2 , Op :: History ( false ) ) ,
139144 act ( 2 , Op :: LineFit ) ,
140145 shot ( 10 , "fitted" ) ,
141146 // The three widths bracket the Ribbon's width budget: 720 steps the
@@ -331,7 +336,7 @@ impl ShotDriver {
331336 . collect ( )
332337 } ) ;
333338 for ( rel, image) in shots {
334- if let Err ( error) = save_png ( & self . dir . join ( format ! ( "{rel}.png" ) ) , & image) {
339+ if let Err ( error) = capture :: save_png ( & self . dir . join ( format ! ( "{rel}.png" ) ) , & image) {
335340 self . fail ( app, ctx, format ! ( "failed to save {rel}: {error}" ) ) ;
336341 return ;
337342 }
@@ -373,6 +378,12 @@ fn run_op(op: Op, app: &mut PlotxApp, ctx: &egui::Context) -> Result<(), String>
373378 Op :: DeltaCursor => delta_cursor ( app) ?,
374379 Op :: PinSymmetry => pin_symmetry ( app) ?,
375380 Op :: RegionResult => region_result ( app) ,
381+ Op :: History ( open) => {
382+ app. session . ui . diagnostics_open = open;
383+ ctx. data_mut ( |data| {
384+ data. insert_temp ( egui:: Id :: new ( "operation_history_messages_tab" ) , true )
385+ } ) ;
386+ }
376387 Op :: RegionData => {
377388 app. session . ui . sheet_open = Some ( 1 ) ;
378389 app. session . ui . curve_fit_task_collapsed = true ;
@@ -754,43 +765,6 @@ fn synthetic_cosy() -> plotx_io::NmrData2D {
754765 }
755766}
756767
757- fn save_png ( path : & Path , image : & egui:: ColorImage ) -> Result < ( ) , String > {
758- if let Some ( parent) = path. parent ( ) {
759- std:: fs:: create_dir_all ( parent)
760- . map_err ( |error| format ! ( "create {}: {error}" , parent. display( ) ) ) ?;
761- }
762- let [ width, height] = image. size ;
763- // egui screenshots are opaque RGBA8, so straight-alpha encoding is exact.
764- image:: save_buffer_with_format (
765- path,
766- image. as_raw ( ) ,
767- width as u32 ,
768- height as u32 ,
769- image:: ColorType :: Rgba8 ,
770- image:: ImageFormat :: Png ,
771- )
772- . map_err ( |error| format ! ( "encode {}: {error}" , path. display( ) ) )
773- }
774-
775768#[ cfg( test) ]
776- mod tests {
777- use super :: * ;
778-
779- #[ test]
780- fn automated_exit_bypasses_dirty_project_prompt ( ) {
781- let mut app = PlotxApp :: new_with_settings ( plotx_core:: settings:: Settings :: default ( ) ) ;
782- app. mark_document_dirty ( ) ;
783- let ctx = egui:: Context :: default ( ) ;
784-
785- let output = ctx. run_ui ( egui:: RawInput :: default ( ) , |ui| {
786- request_exit ( & mut app, ui. ctx ( ) ) ;
787- } ) ;
788-
789- assert ! ( app. session. allow_close) ;
790- let root = output
791- . viewport_output
792- . get ( & egui:: ViewportId :: ROOT )
793- . expect ( "root viewport output" ) ;
794- assert ! ( root. commands. contains( & egui:: ViewportCommand :: Close ) ) ;
795- }
796- }
769+ #[ path = "shot/tests.rs" ]
770+ mod tests;
0 commit comments