Skip to content

Commit 51d53bf

Browse files
committed
extended math notation formula print
1 parent d30a0b7 commit 51d53bf

3 files changed

Lines changed: 108 additions & 21 deletions

File tree

src/app.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ mod points_text;
2323
mod ui;
2424

2525
use self::diagnostics::{IterationDiagnostics, diagnostics_plot_y_axis_width};
26-
#[cfg(target_arch = "wasm32")]
2726
use self::formula::formula_plain_text;
2827
use self::formula::model_formula_info;
2928
#[cfg(not(target_arch = "wasm32"))]
@@ -528,6 +527,7 @@ pub struct CurveFitApp {
528527
active_tool_bounds: Option<PlotBounds>,
529528
show_left_panel: bool,
530529
show_right_panel: bool,
530+
show_formula_window: bool,
531531
show_diagnostics_panel: bool,
532532
diagnostics_hide_non_loss_by_default_pending: bool,
533533
diagnostics_shared_axis_width: f32,
@@ -1556,6 +1556,7 @@ impl Default for CurveFitApp {
15561556
spline_duplicate_x_policy: SplineDuplicateXPolicy::default(),
15571557
spline_initial_knot_y_inputs: Vec::new(),
15581558
show_right_panel: true,
1559+
show_formula_window: false,
15591560
show_diagnostics_panel: true,
15601561
diagnostics_hide_non_loss_by_default_pending: true,
15611562
diagnostics_shared_axis_width: 0.0,
@@ -1617,7 +1618,7 @@ impl eframe::App for CurveFitApp {
16171618
}
16181619

16191620
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
1620-
let ctx = ui.ctx();
1621+
let ctx = ui.ctx().clone();
16211622
let panel_style = ctx.global_style();
16221623
let panel_style = panel_style.as_ref();
16231624

@@ -1707,6 +1708,8 @@ impl eframe::App for CurveFitApp {
17071708
});
17081709
}
17091710

1711+
self.ui_formula_window(&ctx);
1712+
17101713
if self.show_diagnostics_panel {
17111714
egui::Panel::bottom("diagnostics_panel")
17121715
.resizable(true)

src/app/formula.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@ pub(super) fn formula_svg_uri(formula: &str, dark_mode: bool) -> String {
207207
/// Возвращает человекочитаемое текстовое представление формулы.
208208
///
209209
/// Используется как fallback для платформ, где SVG-текст может рендериться нестабильно.
210-
#[cfg(target_arch = "wasm32")]
211210
pub(super) fn formula_plain_text(formula: &str) -> String {
212211
latex_group_to_text(formula)
213212
}

src/app/ui.rs

Lines changed: 103 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,8 @@ impl CurveFitApp {
878878

879879
let formula_info =
880880
model_formula_info(language, self.selected_model, self.polynomial_degree);
881+
let plain_formula = formula_plain_text(&formula_info.full_formula);
882+
let formula_preview = formula_preview_text(&plain_formula, 78);
881883
ui.add_space(2.0);
882884
egui::Frame::new()
883885
.inner_margin(egui::Margin::symmetric(10, 8))
@@ -888,26 +890,29 @@ impl CurveFitApp {
888890
ui.visuals().widgets.noninteractive.bg_stroke.color,
889891
))
890892
.show(ui, |ui| {
893+
ui.horizontal(|ui| {
894+
ui.label(
895+
egui::RichText::new(tr(language, "Model Formula", "Формула модели"))
896+
.strong(),
897+
);
898+
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
899+
if ui
900+
.button(tr(language, "Open formula", "Открыть формулу"))
901+
.clicked()
902+
{
903+
self.show_formula_window = true;
904+
}
905+
});
906+
});
907+
ui.monospace(formula_preview);
891908
ui.label(
892-
egui::RichText::new(tr(language, "Model Formula", "Формула модели")).strong(),
909+
egui::RichText::new(tr(
910+
language,
911+
"Preview only. Open in a separate window to inspect long formulas.",
912+
"Показано превью. Откройте отдельное окно для длинных формул.",
913+
))
914+
.small(),
893915
);
894-
#[cfg(not(target_arch = "wasm32"))]
895-
{
896-
let dark_mode = ui.visuals().dark_mode;
897-
let (svg_uri, svg_bytes) =
898-
self.cached_formula_svg(&formula_info.full_formula, dark_mode);
899-
ui.add(
900-
egui::Image::from_bytes(svg_uri, svg_bytes)
901-
.max_width(ui.available_width())
902-
.fit_to_original_size(1.0),
903-
);
904-
}
905-
#[cfg(target_arch = "wasm32")]
906-
{
907-
let plain_formula = formula_plain_text(&formula_info.full_formula);
908-
let formula_label = egui::RichText::new(plain_formula).monospace();
909-
ui.label(formula_label);
910-
}
911916
ui.label(egui::RichText::new(formula_info.notes).small());
912917
});
913918

@@ -1131,6 +1136,70 @@ impl CurveFitApp {
11311136
}
11321137
}
11331138

1139+
pub(super) fn ui_formula_window(&mut self, ctx: &egui::Context) {
1140+
if !self.show_formula_window {
1141+
return;
1142+
}
1143+
1144+
let language = self.ui_language;
1145+
let formula_info =
1146+
model_formula_info(language, self.selected_model, self.polynomial_degree);
1147+
let plain_formula = formula_plain_text(&formula_info.full_formula);
1148+
let mut is_open = self.show_formula_window;
1149+
egui::Window::new(tr(language, "Model Formula", "Формула модели"))
1150+
.open(&mut is_open)
1151+
.default_size(egui::vec2(760.0, 220.0))
1152+
.min_width(420.0)
1153+
.min_height(140.0)
1154+
.resizable(true)
1155+
.show(ctx, |ui| {
1156+
ui.horizontal_wrapped(|ui| {
1157+
if ui
1158+
.button(tr(language, "Copy formula", "Скопировать формулу"))
1159+
.clicked()
1160+
{
1161+
ui.ctx().copy_text(plain_formula.clone());
1162+
}
1163+
ui.label(
1164+
egui::RichText::new(tr(
1165+
language,
1166+
"Use horizontal scroll for very long formulas.",
1167+
"Для очень длинных формул используйте горизонтальный скролл.",
1168+
))
1169+
.small(),
1170+
);
1171+
});
1172+
ui.add_space(4.0);
1173+
#[cfg(not(target_arch = "wasm32"))]
1174+
{
1175+
let dark_mode = ui.visuals().dark_mode;
1176+
let (svg_uri, svg_bytes) =
1177+
self.cached_formula_svg(&formula_info.full_formula, dark_mode);
1178+
egui::ScrollArea::horizontal()
1179+
.id_salt("formula_window_scroll")
1180+
.auto_shrink([false, true])
1181+
.show(ui, |ui| {
1182+
ui.add(
1183+
egui::Image::from_bytes(svg_uri, svg_bytes)
1184+
.fit_to_original_size(1.0),
1185+
);
1186+
});
1187+
}
1188+
#[cfg(target_arch = "wasm32")]
1189+
{
1190+
egui::ScrollArea::horizontal()
1191+
.id_salt("formula_window_scroll")
1192+
.auto_shrink([false, true])
1193+
.show(ui, |ui| {
1194+
ui.monospace(plain_formula.as_str());
1195+
});
1196+
}
1197+
ui.add_space(4.0);
1198+
ui.label(egui::RichText::new(formula_info.notes).small());
1199+
});
1200+
self.show_formula_window = is_open;
1201+
}
1202+
11341203
pub(super) fn ui_optimizer(&mut self, ui: &mut egui::Ui) {
11351204
let language = self.ui_language;
11361205
let icon_tint = ui.visuals().text_color();
@@ -2114,6 +2183,22 @@ impl CurveFitApp {
21142183
}
21152184
}
21162185

2186+
fn formula_preview_text(formula: &str, max_chars: usize) -> String {
2187+
if max_chars <= 3 {
2188+
return "...".to_string();
2189+
}
2190+
2191+
let total_chars = formula.chars().count();
2192+
if total_chars <= max_chars {
2193+
return formula.to_string();
2194+
}
2195+
2196+
let mut preview = String::with_capacity(max_chars + 3);
2197+
preview.extend(formula.chars().take(max_chars - 3));
2198+
preview.push_str("...");
2199+
preview
2200+
}
2201+
21172202
fn diagnostics_hidden_non_loss_series_ids() -> [egui::Id; 6] {
21182203
[
21192204
egui::Id::new(DIAGNOSTICS_SERIES_ID_MSE),

0 commit comments

Comments
 (0)