mirror of https://codeberg.org/topola/topola.git
egui: source GUI strings from Fluent files
This commit is contained in:
parent
0257568410
commit
4e37f5715b
|
|
@ -1 +1,23 @@
|
|||
reference = simple text with a reference: { -something }
|
||||
menu-file = File
|
||||
menu-debug = Debug
|
||||
|
||||
action-open-dsn = Open
|
||||
action-export-ses = Export session file
|
||||
action-import-cmd = Import history
|
||||
action-export-cmd = Export history
|
||||
|
||||
action-quit = Quit
|
||||
action-autoroute = Autoroute
|
||||
action-place-via = Place Via
|
||||
action-remove-bands = Remove Bands
|
||||
action-compare-detours = Compare Detours
|
||||
|
||||
action-undo = Undo
|
||||
action-redo = Redo
|
||||
|
||||
show-ratsnest = Show Ratsnest
|
||||
show-navmesh = Show Navmesh
|
||||
show-bboxes = Show BBoxes
|
||||
show-origin-destination = Show Origin–Destination
|
||||
|
||||
specctra-session-file = Specctra session file
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ pub struct Action {
|
|||
}
|
||||
|
||||
impl Action {
|
||||
pub fn new(name: &str, modifiers: egui::Modifiers, key: egui::Key) -> Self {
|
||||
pub fn new(name: String, modifiers: egui::Modifiers, key: egui::Key) -> Self {
|
||||
Self {
|
||||
name: String::from(name),
|
||||
name,
|
||||
shortcut: egui::KeyboardShortcut::new(modifiers, key),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,14 +43,14 @@ use topola::{
|
|||
|
||||
use crate::{
|
||||
bottom::Bottom, file_receiver::FileReceiver, layers::Layers, overlay::Overlay,
|
||||
painter::Painter, top::Top, viewport::Viewport,
|
||||
painter::Painter, top::Top, translator::Translator, viewport::Viewport,
|
||||
};
|
||||
|
||||
/// Deserialize/Serialize is needed to persist app state between restarts.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct App {
|
||||
langid: LanguageIdentifier,
|
||||
translator: Translator,
|
||||
|
||||
#[serde(skip)]
|
||||
maybe_overlay: Option<Overlay>,
|
||||
|
|
@ -89,7 +89,7 @@ pub struct App {
|
|||
impl Default for App {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
langid: langid!("en-US"),
|
||||
translator: Translator::new(langid!("en-US")),
|
||||
maybe_overlay: None,
|
||||
arc_mutex_maybe_invoker: Arc::new(Mutex::new(None)),
|
||||
maybe_execute: None,
|
||||
|
|
@ -111,14 +111,14 @@ impl App {
|
|||
// Load previous app state if one exists.
|
||||
if let Some(storage) = cc.storage {
|
||||
let this = Self {
|
||||
langid,
|
||||
translator: Translator::new(langid),
|
||||
..eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default()
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
Self {
|
||||
langid,
|
||||
translator: Translator::new(langid),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -176,6 +176,7 @@ impl eframe::App for App {
|
|||
|
||||
self.top.update(
|
||||
ctx,
|
||||
&self.translator,
|
||||
self.content_channel.0.clone(),
|
||||
self.history_channel.0.clone(),
|
||||
self.arc_mutex_maybe_invoker.clone(),
|
||||
|
|
@ -199,8 +200,13 @@ impl eframe::App for App {
|
|||
&self.maybe_layers,
|
||||
);
|
||||
|
||||
self.bottom
|
||||
.update(ctx, &self.viewport, viewport_rect, &self.maybe_execute);
|
||||
self.bottom.update(
|
||||
ctx,
|
||||
&self.translator,
|
||||
&self.viewport,
|
||||
viewport_rect,
|
||||
&self.maybe_execute,
|
||||
);
|
||||
|
||||
if ctx.input(|i| i.key_pressed(egui::Key::Escape)) {
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use topola::autorouter::invoker::{Execute, ExecuteWithStatus, InvokerStatus};
|
||||
|
||||
use crate::viewport::Viewport;
|
||||
use crate::{translator::Translator, viewport::Viewport};
|
||||
|
||||
pub struct Bottom {}
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ impl Bottom {
|
|||
pub fn update(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
tr: &Translator,
|
||||
viewport: &Viewport,
|
||||
viewport_rect: egui::Rect,
|
||||
maybe_execute: &Option<ExecuteWithStatus>,
|
||||
|
|
|
|||
|
|
@ -9,19 +9,14 @@ mod layers;
|
|||
mod overlay;
|
||||
mod painter;
|
||||
mod top;
|
||||
mod translator;
|
||||
mod viewport;
|
||||
|
||||
use app::App;
|
||||
use fluent_templates::static_loader;
|
||||
use sys_locale::get_locale;
|
||||
use unic_langid::{langid, LanguageIdentifier};
|
||||
|
||||
static_loader! {
|
||||
static LOCALES = {
|
||||
locales: "./locales",
|
||||
fallback_language: "en-US",
|
||||
};
|
||||
}
|
||||
|
||||
// Build to native.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn main() -> eframe::Result<()> {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use crate::{
|
|||
app::{channel_text, execute},
|
||||
file_sender::FileSender,
|
||||
overlay::Overlay,
|
||||
translator::Translator,
|
||||
};
|
||||
|
||||
pub struct Top {
|
||||
|
|
@ -40,6 +41,7 @@ impl Top {
|
|||
pub fn update(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
tr: &Translator,
|
||||
content_sender: Sender<String>,
|
||||
history_sender: Sender<String>,
|
||||
arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>,
|
||||
|
|
@ -47,51 +49,66 @@ impl Top {
|
|||
maybe_overlay: &mut Option<Overlay>,
|
||||
maybe_design: &Option<SpecctraDesign>,
|
||||
) -> Result<(), InvokerError> {
|
||||
let mut open_design =
|
||||
Trigger::new(Action::new("Open", egui::Modifiers::CTRL, egui::Key::O));
|
||||
let mut open_design = Trigger::new(Action::new(
|
||||
tr.text("action-open-dsn"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::O,
|
||||
));
|
||||
let mut export_session = Trigger::new(Action::new(
|
||||
"Export session file",
|
||||
tr.text("action-export-ses"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::S,
|
||||
));
|
||||
let mut import_history = Trigger::new(Action::new(
|
||||
"Import history",
|
||||
tr.text("action-import-cmd"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::I,
|
||||
));
|
||||
let mut export_history = Trigger::new(Action::new(
|
||||
"Export history",
|
||||
tr.text("action-export-cmd"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::E,
|
||||
));
|
||||
let mut quit = Trigger::new(Action::new("Quit", egui::Modifiers::CTRL, egui::Key::V));
|
||||
let mut quit = Trigger::new(Action::new(
|
||||
tr.text("action-quit"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::V,
|
||||
));
|
||||
let mut autoroute = Trigger::new(Action::new(
|
||||
"Autoroute",
|
||||
tr.text("action-autoroute"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::A,
|
||||
));
|
||||
let mut place_via = Switch::new(Action::new(
|
||||
"Place Via",
|
||||
tr.text("action-place-via"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::P,
|
||||
));
|
||||
let mut remove_bands = Trigger::new(Action::new(
|
||||
"Remove Selected Bands",
|
||||
tr.text("action-remove-bands"),
|
||||
egui::Modifiers::NONE,
|
||||
egui::Key::Delete,
|
||||
));
|
||||
let mut compare_detours = Trigger::new(Action::new(
|
||||
"Compare Detours",
|
||||
tr.text("action-compare-detours"),
|
||||
egui::Modifiers::NONE,
|
||||
egui::Key::Minus,
|
||||
));
|
||||
let mut undo = Trigger::new(Action::new("Undo", egui::Modifiers::CTRL, egui::Key::Z));
|
||||
let mut redo = Trigger::new(Action::new("Redo", egui::Modifiers::CTRL, egui::Key::Y));
|
||||
let mut undo = Trigger::new(Action::new(
|
||||
tr.text("action-undo"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::Z,
|
||||
));
|
||||
let mut redo = Trigger::new(Action::new(
|
||||
tr.text("action-redo"),
|
||||
egui::Modifiers::CTRL,
|
||||
egui::Key::Y,
|
||||
));
|
||||
|
||||
egui::TopBottomPanel::top("top_panel")
|
||||
.show(ctx, |ui| {
|
||||
egui::menu::bar(ui, |ui| {
|
||||
ui.menu_button("File", |ui| {
|
||||
ui.menu_button(tr.text("menu-file"), |ui| {
|
||||
open_design.button(ctx, ui);
|
||||
export_session.button(ctx, ui);
|
||||
|
||||
|
|
@ -123,11 +140,14 @@ impl Top {
|
|||
|
||||
ui.separator();
|
||||
|
||||
ui.menu_button("Debug", |ui| {
|
||||
ui.checkbox(&mut self.show_ratsnest, "Show Ratsnest");
|
||||
ui.checkbox(&mut self.show_navmesh, "Show Navmesh");
|
||||
ui.checkbox(&mut self.show_bboxes, "Show BBoxes");
|
||||
ui.checkbox(&mut self.show_origin_destination, "Show Origin–Destination");
|
||||
ui.menu_button(tr.text("menu-debug"), |ui| {
|
||||
ui.checkbox(&mut self.show_ratsnest, tr.text("show-ratsnest"));
|
||||
ui.checkbox(&mut self.show_navmesh, tr.text("show-navmesh"));
|
||||
ui.checkbox(&mut self.show_bboxes, tr.text("show-bboxes"));
|
||||
ui.checkbox(
|
||||
&mut self.show_origin_destination,
|
||||
tr.text("show-origin-destination"),
|
||||
);
|
||||
|
||||
ui.separator();
|
||||
compare_detours.button(ctx, ui);
|
||||
|
|
@ -170,7 +190,7 @@ impl Top {
|
|||
}
|
||||
}
|
||||
let task = dialog
|
||||
.add_filter("Specctra session file", &["ses"])
|
||||
.add_filter(tr.text("specctra-session-file"), &["ses"])
|
||||
.save_file();
|
||||
|
||||
execute(async move {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
use fluent_templates::{static_loader, Loader};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use unic_langid::LanguageIdentifier;
|
||||
|
||||
static_loader! {
|
||||
static LOCALES = {
|
||||
locales: "./locales",
|
||||
fallback_language: "en-US",
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Translator {
|
||||
langid: LanguageIdentifier,
|
||||
}
|
||||
|
||||
impl Translator {
|
||||
pub fn new(langid: LanguageIdentifier) -> Self {
|
||||
Self { langid }
|
||||
}
|
||||
|
||||
pub fn text(&self, fluent_id: &str) -> String {
|
||||
LOCALES.lookup(&self.langid, fluent_id)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
use clap::{Error, Parser};
|
||||
use fluent_templates::static_loader;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
|
|
|
|||
Loading…
Reference in New Issue