mirror of https://codeberg.org/topola/topola.git
egui: add error messages dialog
This commit is contained in:
parent
b738a425e4
commit
82574d2976
|
|
@ -39,3 +39,7 @@ show-layer-manager = Show Layer Manager
|
|||
frame-timestep = Frame Timestep
|
||||
|
||||
specctra-session-file = Specctra session file
|
||||
|
||||
title-error-messages = Error Messages
|
||||
reset-error-messages = Reset Messages
|
||||
discard-item = Discard
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ use topola::{
|
|||
use crate::{
|
||||
activity::{ActivityStatus, ActivityWithStatus},
|
||||
bottom::Bottom,
|
||||
error_dialog::ErrorDialog,
|
||||
file_receiver::FileReceiver,
|
||||
layers::Layers,
|
||||
overlay::Overlay,
|
||||
|
|
@ -79,6 +80,9 @@ pub struct App {
|
|||
#[serde(skip)]
|
||||
bottom: Bottom,
|
||||
|
||||
#[serde(skip)]
|
||||
error_dialog: ErrorDialog,
|
||||
|
||||
#[serde(skip)]
|
||||
maybe_layers: Option<Layers>,
|
||||
|
||||
|
|
@ -101,6 +105,7 @@ impl Default for App {
|
|||
viewport: Viewport::new(),
|
||||
top: Top::new(),
|
||||
bottom: Bottom::new(),
|
||||
error_dialog: ErrorDialog::new(),
|
||||
maybe_layers: None,
|
||||
maybe_design: None,
|
||||
update_counter: 0.0,
|
||||
|
|
@ -206,6 +211,9 @@ impl eframe::App for App {
|
|||
}
|
||||
}
|
||||
|
||||
self.error_dialog
|
||||
.update(ctx, &self.translator, &self.viewport);
|
||||
|
||||
let viewport_rect = self.viewport.update(
|
||||
ctx,
|
||||
&self.top,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
//! dialog for error messages (e.g. for displaying file parser errors)
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{translator::Translator, viewport::Viewport};
|
||||
|
||||
pub struct ErrorDialog {
|
||||
pub messages: Vec<(&'static str, String)>,
|
||||
pub window_open: bool,
|
||||
}
|
||||
|
||||
impl ErrorDialog {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
messages: Vec::new(),
|
||||
window_open: false,
|
||||
}
|
||||
}
|
||||
|
||||
// this is a separate method in order to intercept error messages
|
||||
// and also print them to the console.
|
||||
pub fn push_error(&mut self, component_id: &'static str, message: String) {
|
||||
// note that the message here is already localized, and perhaps less useful.
|
||||
log::info!("{}: {}", component_id, &message);
|
||||
self.messages.push((component_id, message));
|
||||
self.window_open = true;
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ctx: &egui::Context, tr: &Translator, viewport: &Viewport) {
|
||||
let mut messages_cleared = false;
|
||||
egui::Window::new(tr.text("title-error-messages"))
|
||||
.id("error-messages-dialog".into())
|
||||
.open(&mut self.window_open)
|
||||
.scroll(true)
|
||||
.show(ctx, |ui| {
|
||||
if ui.button(tr.text("reset-error-messages")).clicked() {
|
||||
self.messages.clear();
|
||||
messages_cleared = true;
|
||||
}
|
||||
|
||||
egui::Grid::new("error-messages-grid").show(ui, |ui| {
|
||||
let mut messages_to_discard = BTreeSet::<usize>::new();
|
||||
let style = Arc::clone(ui.style());
|
||||
for (msg_id, msg) in self.messages.iter().enumerate() {
|
||||
use egui::style::{FontSelection, TextStyle};
|
||||
use egui::text::{LayoutJob, TextWrapping};
|
||||
use egui::widget_text::{RichText, WidgetText};
|
||||
use egui::{Align, FontFamily, FontId, TextFormat};
|
||||
|
||||
let mut loj = LayoutJob::default();
|
||||
loj.break_on_newline = true;
|
||||
loj.wrap.max_width = 200.0;
|
||||
RichText::new(&(tr.text(msg.0) + ": "))
|
||||
.strong()
|
||||
.color(style.visuals.text_color())
|
||||
.append_to(&mut loj, &style, FontSelection::Default, Align::Min);
|
||||
RichText::new(&msg.1)
|
||||
.color(style.visuals.text_color())
|
||||
.append_to(
|
||||
&mut loj,
|
||||
&style,
|
||||
FontSelection::Style(TextStyle::Monospace),
|
||||
Align::Min,
|
||||
);
|
||||
|
||||
// TODO: perhaps alternatively, use small icon instead?
|
||||
// (provide alt text in that case!)
|
||||
if ui.add(egui::Button::new(tr.text("discard-item"))).clicked() {
|
||||
messages_to_discard.insert(msg_id);
|
||||
}
|
||||
ui.label(WidgetText::LayoutJob(loj));
|
||||
ui.end_row();
|
||||
}
|
||||
if !messages_to_discard.is_empty() {
|
||||
let mut count = 0;
|
||||
self.messages.retain(|_| {
|
||||
let ret = !messages_to_discard.contains(&count);
|
||||
count += 1;
|
||||
ret
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if messages_cleared {
|
||||
self.window_open = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ mod action;
|
|||
mod activity;
|
||||
mod app;
|
||||
mod bottom;
|
||||
mod error_dialog;
|
||||
mod file_receiver;
|
||||
mod file_sender;
|
||||
mod layers;
|
||||
|
|
|
|||
Loading…
Reference in New Issue