Skip to content

Commit 0a4d67a

Browse files
committed
ui minimization
1 parent cdce33d commit 0a4d67a

12 files changed

Lines changed: 323 additions & 176 deletions

File tree

assets/icons/tabler/dots.svg

Lines changed: 21 additions & 0 deletions
Loading
Lines changed: 23 additions & 0 deletions
Loading

src/app.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ use self::formula::model_formula_info;
3232
#[cfg(not(target_arch = "wasm32"))]
3333
use self::formula::{formula_svg_bytes, formula_svg_uri};
3434
use self::i18n::{
35-
center_origin_icon_image, clear_icon_image, family_label, fit_icon_image,
35+
actions_icon_image, center_origin_icon_image, clear_icon_image, family_label, fit_icon_image,
3636
fit_to_content_icon_image, github_mark_image, language_flag_image, model_choice_label,
3737
open_formula_icon_image, optimization_loss_metric_label, origin_bottom_left_icon_image,
3838
panels_icon_image, param_init_method_disabled_label, param_init_method_label,
3939
param_init_method_name_en, redo_icon_image, replay_pause_icon_image, replay_play_icon_image,
4040
reset_icon_image, spline_extrapolation_label, spline_knot_strategy_label, spray_brush_label,
41-
stop_icon_image, tool_icon_image, tool_label, tr, undo_icon_image, view_icon_image,
41+
stop_icon_image, tool_icon_image, tr, undo_icon_image, view_icon_image,
4242
};
4343
use self::normalization::ParametricNormalization;
4444
use self::optimizer::{
@@ -178,6 +178,7 @@ enum PlotTool {
178178
None,
179179
#[default]
180180
SinglePoint,
181+
Dotted,
181182
Spray,
182183
Eraser,
183184
}

src/app/i18n.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ pub(super) fn clear_icon_image(tint: egui::Color32) -> egui::Image<'static> {
7676
tabler_icon!("../../assets/icons/tabler/clear-all.svg", tint)
7777
}
7878

79+
pub(super) fn actions_icon_image(tint: egui::Color32) -> egui::Image<'static> {
80+
tabler_icon!("../../assets/icons/tabler/dots.svg", tint)
81+
}
82+
7983
pub(super) fn reset_icon_image(tint: egui::Color32) -> egui::Image<'static> {
8084
tabler_icon!("../../assets/icons/tabler/restore.svg", tint)
8185
}
@@ -100,24 +104,12 @@ pub(super) fn tool_icon_image(tool: PlotTool, tint: egui::Color32) -> egui::Imag
100104
match tool {
101105
PlotTool::None => tabler_icon!("../../assets/icons/tabler/pointer.svg", tint),
102106
PlotTool::SinglePoint => tabler_icon!("../../assets/icons/tabler/point.svg", tint),
107+
PlotTool::Dotted => tabler_icon!("../../assets/icons/tabler/line-dotted.svg", tint),
103108
PlotTool::Spray => tabler_icon!("../../assets/icons/tabler/spray.svg", tint),
104109
PlotTool::Eraser => tabler_icon!("../../assets/icons/tabler/eraser.svg", tint),
105110
}
106111
}
107112

108-
pub(super) fn tool_label(language: UiLanguage, tool: PlotTool) -> &'static str {
109-
match (language, tool) {
110-
(UiLanguage::English, PlotTool::None) => "None",
111-
(UiLanguage::English, PlotTool::SinglePoint) => "Point",
112-
(UiLanguage::English, PlotTool::Spray) => "Spray",
113-
(UiLanguage::English, PlotTool::Eraser) => "Eraser",
114-
(UiLanguage::Russian, PlotTool::None) => "Навигация",
115-
(UiLanguage::Russian, PlotTool::SinglePoint) => "Точка",
116-
(UiLanguage::Russian, PlotTool::Spray) => "Спрей",
117-
(UiLanguage::Russian, PlotTool::Eraser) => "Ластик",
118-
}
119-
}
120-
121113
pub(super) fn spray_brush_label(language: UiLanguage, brush: SprayBrush) -> &'static str {
122114
match (language, brush) {
123115
(UiLanguage::English, SprayBrush::Uniform) => "Uniform",

src/app/ui.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -203,34 +203,19 @@ impl CurveFitApp {
203203
) -> egui::Response {
204204
ui.horizontal(|ui| {
205205
let switch_response = Self::toggle_switch(ui, on);
206-
let mut label_response = ui.add(egui::Label::new(label).sense(egui::Sense::click()));
207-
if label_response.clicked() {
208-
*on = !*on;
209-
label_response.mark_changed();
210-
}
211-
switch_response | label_response
206+
ui.label(label);
207+
switch_response
212208
})
213209
.inner
214210
}
215211

216-
fn info_tooltip(ui: &mut egui::Ui, text: impl AsRef<str>) -> egui::Response {
212+
fn info_hover(response: egui::Response, text: impl AsRef<str>) -> egui::Response {
217213
let lines = text
218214
.as_ref()
219215
.lines()
220216
.map(str::trim)
221217
.filter(|line| !line.is_empty())
222218
.collect::<Vec<_>>();
223-
let response = ui
224-
.add(
225-
egui::Label::new(
226-
egui::RichText::new("ℹ")
227-
.small()
228-
.color(ui.visuals().weak_text_color()),
229-
)
230-
.sense(egui::Sense::hover()),
231-
)
232-
.on_hover_cursor(egui::CursorIcon::Default);
233-
234219
response.on_hover_ui(|ui| {
235220
ui.set_max_width(380.0);
236221
ui.spacing_mut().item_spacing.y = 3.0;

src/app/ui/family_params.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ pub(super) fn ui_family_and_params(app: &mut CurveFitApp, ui: &mut egui::Ui) {
6666
))
6767
.show(ui, |ui| {
6868
ui.horizontal(|ui| {
69-
ui.label(
69+
let formula_label_response = ui.label(
7070
egui::RichText::new(tr(language, "Model Formula", "Формула модели")).strong(),
7171
);
72-
CurveFitApp::info_tooltip(ui, formula_help.as_str());
72+
let _ = CurveFitApp::info_hover(formula_label_response, formula_help.as_str());
7373
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
7474
if ui
7575
.add(egui::Button::image(open_formula_icon_image(icon_tint)))
@@ -87,8 +87,9 @@ pub(super) fn ui_family_and_params(app: &mut CurveFitApp, ui: &mut egui::Ui) {
8787
let mut method_to_apply = None;
8888
let mut apply_fitted_init = false;
8989
ui.horizontal_wrapped(|ui| {
90-
ui.label(tr(language, "Initial parameters", "Начальные параметры"));
91-
CurveFitApp::info_tooltip(ui, parametric_init_hint(language));
90+
let init_label_response =
91+
ui.label(tr(language, "Initial parameters", "Начальные параметры"));
92+
let _ = CurveFitApp::info_hover(init_label_response, parametric_init_hint(language));
9293
ui.add_enabled_ui(can_edit_params, |ui| {
9394
ui.menu_button(
9495
tr(language, "+ Initialize", "+ Инициализация"),
@@ -123,11 +124,16 @@ pub(super) fn ui_family_and_params(app: &mut CurveFitApp, ui: &mut egui::Ui) {
123124
ui.close();
124125
}
125126
} else {
126-
ui.add_enabled(
127-
false,
128-
egui::Button::new(param_init_method_disabled_label(
129-
language, method,
130-
)),
127+
let unavailable_label = format!(
128+
"{} ({})",
129+
param_init_method_label(language, method),
130+
tr(language, "not available", "недоступно")
131+
);
132+
let unavailable_response =
133+
ui.add_enabled(false, egui::Button::new(unavailable_label));
134+
let _ = CurveFitApp::info_hover(
135+
unavailable_response,
136+
param_init_method_disabled_label(language, method),
131137
);
132138
}
133139
}
@@ -166,8 +172,9 @@ pub(super) fn ui_family_and_params(app: &mut CurveFitApp, ui: &mut egui::Ui) {
166172
let mut spline_method_to_apply = None;
167173

168174
ui.horizontal_wrapped(|ui| {
169-
ui.label(tr(language, "Initial parameters", "Начальные параметры"));
170-
CurveFitApp::info_tooltip(ui, spline_init_hint(language));
175+
let init_label_response =
176+
ui.label(tr(language, "Initial parameters", "Начальные параметры"));
177+
let _ = CurveFitApp::info_hover(init_label_response, spline_init_hint(language));
171178
ui.add_enabled_ui(can_edit_params, |ui| {
172179
ui.menu_button(
173180
tr(language, "+ Initialize", "+ Инициализация"),
@@ -250,7 +257,7 @@ pub(super) fn ui_family_and_params(app: &mut CurveFitApp, ui: &mut egui::Ui) {
250257
});
251258
app.sync_spline_initial_knot_y_inputs(app.spline_knots);
252259
ui.horizontal_wrapped(|ui| {
253-
ui.label(format!(
260+
let spline_sampling_response = ui.label(format!(
254261
"{}: {}",
255262
tr(
256263
language,
@@ -259,7 +266,8 @@ pub(super) fn ui_family_and_params(app: &mut CurveFitApp, ui: &mut egui::Ui) {
259266
),
260267
app.spline_knots
261268
));
262-
CurveFitApp::info_tooltip(ui, spline_sampling_hint(language));
269+
let _ =
270+
CurveFitApp::info_hover(spline_sampling_response, spline_sampling_hint(language));
263271
});
264272
ui.label(tr(
265273
language,

src/app/ui/formula_window.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,19 @@ pub(super) fn ui_formula_window(app: &mut CurveFitApp, ctx: &egui::Context) {
1616
.min_height(140.0)
1717
.resizable(true)
1818
.show(ctx, |ui| {
19+
let formula_window_hint = tr(
20+
language,
21+
"Formula window\n- Use horizontal scroll for very long formulas\n- Copy formula exports plain-text representation",
22+
"Окно формулы\n- Для очень длинных формул используйте горизонтальный скролл\n- Копирование формулы экспортирует текстовое представление",
23+
);
1924
ui.horizontal_wrapped(|ui| {
20-
if ui
21-
.button(tr(language, "Copy formula", "Скопировать формулу"))
22-
.clicked()
23-
{
25+
let copy_response = CurveFitApp::info_hover(
26+
ui.button(tr(language, "Copy formula", "Скопировать формулу")),
27+
formula_window_hint,
28+
);
29+
if copy_response.clicked() {
2430
ui.ctx().copy_text(plain_formula.clone());
2531
}
26-
CurveFitApp::info_tooltip(
27-
ui,
28-
tr(
29-
language,
30-
"Formula window\n- Use horizontal scroll for very long formulas\n- Copy formula exports plain-text representation",
31-
"Окно формулы\n- Для очень длинных формул используйте горизонтальный скролл\n- Копирование формулы экспортирует текстовое представление",
32-
),
33-
);
3432
});
3533
ui.add_space(4.0);
3634
#[cfg(not(target_arch = "wasm32"))]

src/app/ui/header_bar.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,25 @@ pub(super) fn ui_header(app: &mut CurveFitApp, ui: &mut egui::Ui) {
8080
let mut selected_iteration =
8181
app.replay_selected_iteration().unwrap_or(min_iteration);
8282
let replay_slider_enabled = !app.fit_in_progress && !app.replay.frames.is_empty();
83-
let response = ui.add_enabled(
84-
replay_slider_enabled,
85-
egui::Slider::new(&mut selected_iteration, min_iteration..=max_iteration)
86-
.text(tr(language, "Displayed iteration", "Показываемая итерация")),
83+
let replay_hint = replay_controls_hint(language);
84+
let response = CurveFitApp::info_hover(
85+
ui.add_enabled(
86+
replay_slider_enabled,
87+
egui::Slider::new(&mut selected_iteration, min_iteration..=max_iteration)
88+
.text(tr(language, "Displayed iteration", "Показываемая итерация")),
89+
),
90+
replay_hint,
8791
);
8892
if replay_slider_enabled && response.changed() {
8993
app.pause_replay();
9094
app.select_nearest_replay_iteration(selected_iteration);
9195
}
92-
CurveFitApp::toggle_switch_labeled(
96+
let autoplay_response = CurveFitApp::toggle_switch_labeled(
9397
ui,
9498
&mut app.replay.autoplay_on_fit,
9599
tr(language, "Auto-play", "Автопромотка"),
96100
);
101+
let _ = CurveFitApp::info_hover(autoplay_response, replay_hint);
97102
let (play_icon, play_label) = if app.replay.autoplay {
98103
(
99104
replay_pause_icon_image(icon_tint),
@@ -106,22 +111,23 @@ pub(super) fn ui_header(app: &mut CurveFitApp, ui: &mut egui::Ui) {
106111
)
107112
};
108113
let can_toggle_play = !app.fit_in_progress && app.replay.frames.len() > 1;
109-
if ui
110-
.add_enabled(
114+
let play_response = CurveFitApp::info_hover(
115+
ui.add_enabled(
111116
can_toggle_play,
112117
egui::Button::image_and_text(play_icon, play_label),
113-
)
114-
.clicked()
115-
{
118+
),
119+
replay_hint,
120+
);
121+
if play_response.clicked() {
116122
app.toggle_replay_autoplay();
117123
}
118-
CurveFitApp::info_tooltip(ui, replay_controls_hint(language));
119124
ui.separator();
120-
ui.add(
125+
let replay_step_response = ui.add(
121126
egui::Slider::new(&mut app.replay.iteration_delay_seconds, 0.0..=3.0)
122127
.step_by(0.01)
123128
.text(tr(language, "Replay step, sec", "Шаг промотки, сек")),
124129
);
130+
let _ = CurveFitApp::info_hover(replay_step_response, replay_hint);
125131
});
126132
});
127133
}

src/app/ui/optimizer_panel.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,24 @@ pub(super) fn ui_optimizer(app: &mut CurveFitApp, ui: &mut egui::Ui) {
1919
}
2020
});
2121
ui.horizontal_wrapped(|ui| {
22-
ui.selectable_value(
22+
let basic_response = ui.selectable_value(
2323
&mut app.optimizer_mode,
2424
OptimizerUiMode::Basic,
2525
tr(language, "Basic", "Базовый"),
2626
);
27-
ui.selectable_value(
27+
let _ = CurveFitApp::info_hover(
28+
basic_response,
29+
optimizer_mode_hint(language, OptimizerUiMode::Basic),
30+
);
31+
let advanced_response = ui.selectable_value(
2832
&mut app.optimizer_mode,
2933
OptimizerUiMode::Advanced,
3034
tr(language, "Advanced", "Продвинутый"),
3135
);
32-
CurveFitApp::info_tooltip(ui, optimizer_mode_hint(language, app.optimizer_mode));
36+
let _ = CurveFitApp::info_hover(
37+
advanced_response,
38+
optimizer_mode_hint(language, OptimizerUiMode::Advanced),
39+
);
3340
});
3441

3542
if app.optimizer_mode == OptimizerUiMode::Basic {

0 commit comments

Comments
 (0)