@@ -12,6 +12,7 @@ use egui_plot::{
1212 Points as PlotPointsItem , VLine ,
1313} ;
1414
15+ mod clipboard_import;
1516mod diagnostics;
1617mod fit_worker;
1718mod formula;
@@ -32,13 +33,14 @@ use self::formula::model_formula_info;
3233#[ cfg( not( target_arch = "wasm32" ) ) ]
3334use self :: formula:: { formula_svg_bytes, formula_svg_uri} ;
3435use self :: i18n:: {
35- actions_icon_image, center_origin_icon_image, clear_icon_image, family_label, fit_icon_image,
36- fit_to_content_icon_image, github_mark_image, language_flag_image, model_choice_label,
37- open_formula_icon_image, optimization_loss_metric_label, origin_bottom_left_icon_image,
38- panels_icon_image, param_init_method_disabled_label, param_init_method_label,
39- param_init_method_name_en, redo_icon_image, replay_pause_icon_image, replay_play_icon_image,
40- reset_icon_image, spline_extrapolation_label, spline_knot_strategy_label, spray_brush_label,
41- stop_icon_image, tool_icon_image, tr, undo_icon_image, view_icon_image,
36+ actions_icon_image, center_origin_icon_image, clear_icon_image, clipboard_import_icon_image,
37+ family_label, fit_icon_image, fit_to_content_icon_image, github_mark_image,
38+ language_flag_image, model_choice_label, open_formula_icon_image,
39+ optimization_loss_metric_label, origin_bottom_left_icon_image, panels_icon_image,
40+ param_init_method_disabled_label, param_init_method_label, param_init_method_name_en,
41+ redo_icon_image, replay_pause_icon_image, replay_play_icon_image, reset_icon_image,
42+ spline_extrapolation_label, spline_knot_strategy_label, spray_brush_label, stop_icon_image,
43+ tool_icon_image, tr, undo_icon_image, view_icon_image,
4244} ;
4345use self :: normalization:: ParametricNormalization ;
4446use self :: optimizer:: {
@@ -54,7 +56,9 @@ use self::param_init::{
5456} ;
5557use self :: plot_utils:: { fit_bounds_for_content, plot_domain} ;
5658use self :: points_state:: { ParsedPointsCache , PointsEditorState } ;
57- use self :: points_text:: { parse_f64, parse_points_text_cache, points_to_text} ;
59+ use self :: points_text:: {
60+ parse_f64, parse_points_from_clipboard_text, parse_points_text_cache, points_to_text,
61+ } ;
5862use self :: replay:: ReplayState ;
5963#[ cfg( test) ]
6064use self :: replay:: { ReplayFrame , ReplayFramePayload } ;
@@ -86,6 +90,8 @@ use crate::fit::{IncrementalSplineFitRunner, IncrementalSplineFitStep};
8690use std:: sync:: atomic:: { AtomicBool , Ordering } ;
8791#[ cfg( not( target_arch = "wasm32" ) ) ]
8892use std:: sync:: mpsc:: { self , Receiver , TryRecvError } ;
93+ #[ cfg( target_arch = "wasm32" ) ]
94+ use std:: { cell:: RefCell , rc:: Rc } ;
8995
9096const PARAMETRIC_PLOT_SAMPLES : usize = 200 ;
9197const C1_MIN : f64 = 1e-8 ;
@@ -109,6 +115,9 @@ const RIGHT_PANEL_MIN_WIDTH: f32 = 280.0;
109115const POINTS_PARSE_DEBOUNCE_MS : u64 = 180 ;
110116const POINTS_HISTORY_LIMIT : usize = 256 ;
111117const POINTS_PARSE_ERROR_PREFIX : & str = "Points parse error: " ;
118+ const CLIPBOARD_IMPORT_ERROR_PREFIX : & str = "Clipboard import error: " ;
119+ #[ cfg( not( target_arch = "wasm32" ) ) ]
120+ const CLIPBOARD_IMPORT_PASTE_TIMEOUT_MS : u64 = 1_500 ;
112121const POINTS_POSITIVE_AXIS_EPS : f64 = 1e-6 ;
113122const UI_CORNER_RADIUS : u8 = 6 ;
114123const PANEL_INNER_MARGIN_X : i8 = 10 ;
@@ -701,6 +710,14 @@ enum WasmFitJob {
701710/// Состояние и UI-логика интерактивного приложения для подгонки кривых.
702711pub struct CurveFitApp {
703712 points : PointsEditorState ,
713+ #[ cfg( not( target_arch = "wasm32" ) ) ]
714+ clipboard_import_request_pending : bool ,
715+ #[ cfg( not( target_arch = "wasm32" ) ) ]
716+ clipboard_import_requested_at : Option < Instant > ,
717+ #[ cfg( target_arch = "wasm32" ) ]
718+ clipboard_import_web_in_flight : bool ,
719+ #[ cfg( target_arch = "wasm32" ) ]
720+ clipboard_import_web_result : Rc < RefCell < Option < Result < String , String > > > > ,
704721 selected_model : ModelChoice ,
705722 polynomial_degree : usize ,
706723 parameter_inputs : Vec < String > ,
@@ -1316,6 +1333,14 @@ impl Default for CurveFitApp {
13161333
13171334 Self {
13181335 points : PointsEditorState :: default ( ) ,
1336+ #[ cfg( not( target_arch = "wasm32" ) ) ]
1337+ clipboard_import_request_pending : false ,
1338+ #[ cfg( not( target_arch = "wasm32" ) ) ]
1339+ clipboard_import_requested_at : None ,
1340+ #[ cfg( target_arch = "wasm32" ) ]
1341+ clipboard_import_web_in_flight : false ,
1342+ #[ cfg( target_arch = "wasm32" ) ]
1343+ clipboard_import_web_result : Rc :: new ( RefCell :: new ( None ) ) ,
13191344 selected_model,
13201345 polynomial_degree,
13211346 parameter_inputs : params_to_input_strings ( & selected_family. default_params ( ) ) ,
@@ -1395,6 +1420,7 @@ impl eframe::App for CurveFitApp {
13951420 Self :: apply_visual_style ( ctx) ;
13961421 self . poll_fit_worker ( ctx) ;
13971422 self . tick_replay ( ctx) ;
1423+ self . poll_points_clipboard_import ( ctx) ;
13981424 self . maybe_refresh_points_cache_after_debounce ( ) ;
13991425
14001426 if !self . fit_in_progress {
0 commit comments