mirror of https://codeberg.org/topola/topola.git
egui: rename "top" and "bottom" to "menu bar" and "status bar"
These are more recognizable terms.
This commit is contained in:
parent
f4d7d5a5a5
commit
001e4bcdcf
|
|
@ -39,13 +39,13 @@ use topola::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
activity::{ActivityStatus, ActivityWithStatus},
|
activity::{ActivityStatus, ActivityWithStatus},
|
||||||
bottom::Bottom,
|
|
||||||
error_dialog::ErrorDialog,
|
error_dialog::ErrorDialog,
|
||||||
file_receiver::FileReceiver,
|
file_receiver::FileReceiver,
|
||||||
layers::Layers,
|
layers::Layers,
|
||||||
|
menu_bar::MenuBar,
|
||||||
overlay::Overlay,
|
overlay::Overlay,
|
||||||
painter::Painter,
|
painter::Painter,
|
||||||
top::Top,
|
status_bar::StatusBar,
|
||||||
translator::Translator,
|
translator::Translator,
|
||||||
viewport::Viewport,
|
viewport::Viewport,
|
||||||
};
|
};
|
||||||
|
|
@ -75,10 +75,10 @@ pub struct App {
|
||||||
viewport: Viewport,
|
viewport: Viewport,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
top: Top,
|
top: MenuBar,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
bottom: Bottom,
|
bottom: StatusBar,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
error_dialog: ErrorDialog,
|
error_dialog: ErrorDialog,
|
||||||
|
|
@ -103,8 +103,8 @@ impl Default for App {
|
||||||
content_channel: channel(),
|
content_channel: channel(),
|
||||||
history_channel: channel(),
|
history_channel: channel(),
|
||||||
viewport: Viewport::new(),
|
viewport: Viewport::new(),
|
||||||
top: Top::new(),
|
top: MenuBar::new(),
|
||||||
bottom: Bottom::new(),
|
bottom: StatusBar::new(),
|
||||||
error_dialog: ErrorDialog::new(),
|
error_dialog: ErrorDialog::new(),
|
||||||
maybe_layers: None,
|
maybe_layers: None,
|
||||||
maybe_design: None,
|
maybe_design: None,
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
use topola::autorouter::invoker::InvokerStatus;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
activity::{ActivityStatus, ActivityWithStatus},
|
|
||||||
translator::Translator,
|
|
||||||
viewport::Viewport,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Bottom {}
|
|
||||||
|
|
||||||
impl Bottom {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(
|
|
||||||
&mut self,
|
|
||||||
ctx: &egui::Context,
|
|
||||||
tr: &Translator,
|
|
||||||
viewport: &Viewport,
|
|
||||||
maybe_activity: &Option<ActivityWithStatus>,
|
|
||||||
) {
|
|
||||||
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
|
|
||||||
let latest_pos = viewport.transform.inverse()
|
|
||||||
* ctx.input(|i| i.pointer.latest_pos().unwrap_or_default());
|
|
||||||
|
|
||||||
let mut message = String::from("");
|
|
||||||
|
|
||||||
if let Some(activity) = maybe_activity {
|
|
||||||
if let Some(ActivityStatus::Finished(msg)) = activity.maybe_status() {
|
|
||||||
message = msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.label(format!(
|
|
||||||
"x: {} y: {} \t {}",
|
|
||||||
latest_pos.x, -latest_pos.y, message
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,14 +3,14 @@
|
||||||
mod action;
|
mod action;
|
||||||
mod activity;
|
mod activity;
|
||||||
mod app;
|
mod app;
|
||||||
mod bottom;
|
|
||||||
mod error_dialog;
|
mod error_dialog;
|
||||||
mod file_receiver;
|
mod file_receiver;
|
||||||
mod file_sender;
|
mod file_sender;
|
||||||
mod layers;
|
mod layers;
|
||||||
|
mod menu_bar;
|
||||||
mod overlay;
|
mod overlay;
|
||||||
mod painter;
|
mod painter;
|
||||||
mod top;
|
mod status_bar;
|
||||||
mod translator;
|
mod translator;
|
||||||
mod viewport;
|
mod viewport;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,378 +0,0 @@
|
||||||
use std::{
|
|
||||||
fs::File,
|
|
||||||
path::Path,
|
|
||||||
sync::{mpsc::Sender, Arc, Mutex},
|
|
||||||
};
|
|
||||||
|
|
||||||
use topola::{
|
|
||||||
autorouter::{
|
|
||||||
execute::Command,
|
|
||||||
invoker::{Invoker, InvokerError, InvokerStatus},
|
|
||||||
AutorouterOptions,
|
|
||||||
},
|
|
||||||
router::RouterOptions,
|
|
||||||
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
action::{Action, Switch, Trigger},
|
|
||||||
activity::{ActivityStatus, ActivityWithStatus},
|
|
||||||
app::execute,
|
|
||||||
file_sender::FileSender,
|
|
||||||
overlay::Overlay,
|
|
||||||
translator::Translator,
|
|
||||||
viewport::Viewport,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Top {
|
|
||||||
pub autorouter_options: AutorouterOptions,
|
|
||||||
pub is_placing_via: bool,
|
|
||||||
pub show_ratsnest: bool,
|
|
||||||
pub show_navmesh: bool,
|
|
||||||
pub show_bboxes: bool,
|
|
||||||
pub show_origin_destination: bool,
|
|
||||||
pub show_layer_manager: bool,
|
|
||||||
pub frame_timestep: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Top {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
autorouter_options: AutorouterOptions {
|
|
||||||
presort_by_pairwise_detours: false,
|
|
||||||
router_options: RouterOptions {
|
|
||||||
wrap_around_bands: true,
|
|
||||||
squeeze_under_bands: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
is_placing_via: false,
|
|
||||||
show_ratsnest: false,
|
|
||||||
show_navmesh: false,
|
|
||||||
show_bboxes: false,
|
|
||||||
show_origin_destination: false,
|
|
||||||
show_layer_manager: true,
|
|
||||||
frame_timestep: 0.1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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>>>>,
|
|
||||||
maybe_activity: &mut Option<ActivityWithStatus>,
|
|
||||||
viewport: &mut Viewport,
|
|
||||||
maybe_overlay: &mut Option<Overlay>,
|
|
||||||
maybe_design: &Option<SpecctraDesign>,
|
|
||||||
) -> Result<(), InvokerError> {
|
|
||||||
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(
|
|
||||||
tr.text("action-export-ses"),
|
|
||||||
egui::Modifiers::CTRL,
|
|
||||||
egui::Key::S,
|
|
||||||
));
|
|
||||||
let mut import_history = Trigger::new(Action::new(
|
|
||||||
tr.text("action-import-cmd"),
|
|
||||||
egui::Modifiers::CTRL,
|
|
||||||
egui::Key::I,
|
|
||||||
));
|
|
||||||
let mut export_history = Trigger::new(Action::new(
|
|
||||||
tr.text("action-export-cmd"),
|
|
||||||
egui::Modifiers::CTRL,
|
|
||||||
egui::Key::E,
|
|
||||||
));
|
|
||||||
let mut quit = Trigger::new(Action::new(
|
|
||||||
tr.text("action-quit"),
|
|
||||||
egui::Modifiers::CTRL,
|
|
||||||
egui::Key::Q,
|
|
||||||
));
|
|
||||||
let mut autoroute = Trigger::new(Action::new(
|
|
||||||
tr.text("action-autoroute"),
|
|
||||||
egui::Modifiers::CTRL,
|
|
||||||
egui::Key::A,
|
|
||||||
));
|
|
||||||
let mut place_via = Switch::new(Action::new(
|
|
||||||
tr.text("action-place-via"),
|
|
||||||
egui::Modifiers::CTRL,
|
|
||||||
egui::Key::P,
|
|
||||||
));
|
|
||||||
let mut remove_bands = Trigger::new(Action::new(
|
|
||||||
tr.text("action-remove-bands"),
|
|
||||||
egui::Modifiers::NONE,
|
|
||||||
egui::Key::Delete,
|
|
||||||
));
|
|
||||||
let mut compare_detours = Trigger::new(Action::new(
|
|
||||||
tr.text("action-compare-detours"),
|
|
||||||
egui::Modifiers::NONE,
|
|
||||||
egui::Key::Minus,
|
|
||||||
));
|
|
||||||
let mut measure_length = Trigger::new(Action::new(
|
|
||||||
tr.text("action-measure-length"),
|
|
||||||
egui::Modifiers::NONE,
|
|
||||||
egui::Key::Plus,
|
|
||||||
));
|
|
||||||
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(tr.text("menu-file"), |ui| {
|
|
||||||
open_design.button(ctx, ui);
|
|
||||||
export_session.button(ctx, ui);
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
import_history.button(ctx, ui);
|
|
||||||
export_history.button(ctx, ui);
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
// "Quit" button wouldn't work on a Web page.
|
|
||||||
if !cfg!(target_arch = "wasm32") {
|
|
||||||
quit.button(ctx, ui);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.menu_button(tr.text("menu-edit"), |ui| {
|
|
||||||
undo.button(ctx, ui);
|
|
||||||
redo.button(ctx, ui);
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
remove_bands.button(ctx, ui);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.menu_button(tr.text("menu-view"), |ui| {
|
|
||||||
ui.toggle_value(
|
|
||||||
&mut viewport.scheduled_zoom_to_fit,
|
|
||||||
tr.text("zoom-to-fit"),
|
|
||||||
);
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
ui.checkbox(&mut self.show_layer_manager, tr.text("show-layer-manager"));
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
ui.label(tr.text("frame-timestep"));
|
|
||||||
ui.add(
|
|
||||||
egui::widgets::Slider::new(&mut self.frame_timestep, 0.0..=3.0)
|
|
||||||
.suffix(" s"),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.menu_button(tr.text("menu-place"), |ui| {
|
|
||||||
place_via.toggle_widget(ctx, ui, &mut self.is_placing_via);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.menu_button(tr.text("menu-route"), |ui| {
|
|
||||||
autoroute.button(ctx, ui);
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
ui.menu_button(tr.text("menu-options"), |ui| {
|
|
||||||
ui.checkbox(
|
|
||||||
&mut self.autorouter_options.presort_by_pairwise_detours,
|
|
||||||
tr.text("presort-by-pairwise-detours"),
|
|
||||||
);
|
|
||||||
ui.checkbox(
|
|
||||||
&mut self.autorouter_options.router_options.squeeze_under_bands,
|
|
||||||
tr.text("squeeze-under-bands"),
|
|
||||||
);
|
|
||||||
ui.checkbox(
|
|
||||||
&mut self.autorouter_options.router_options.wrap_around_bands,
|
|
||||||
tr.text("wrap-around-bands"),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.menu_button(tr.text("menu-inspect"), |ui| {
|
|
||||||
compare_detours.button(ctx, ui);
|
|
||||||
measure_length.button(ctx, ui);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
egui::widgets::global_dark_light_mode_buttons(ui);
|
|
||||||
});
|
|
||||||
|
|
||||||
if open_design.consume_key_triggered(ctx, ui) {
|
|
||||||
// NOTE: On Linux, this requires Zenity to be installed on your system.
|
|
||||||
let ctx = ctx.clone();
|
|
||||||
let task = rfd::AsyncFileDialog::new().pick_file();
|
|
||||||
|
|
||||||
execute(async move {
|
|
||||||
if let Some(file_handle) = task.await {
|
|
||||||
let file_sender = FileSender::new(content_sender);
|
|
||||||
file_sender.send(file_handle).await;
|
|
||||||
ctx.request_repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if export_session.consume_key_triggered(ctx, ui) {
|
|
||||||
if let Some(design) = maybe_design {
|
|
||||||
if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_ref() {
|
|
||||||
let ctx = ui.ctx().clone();
|
|
||||||
let board = invoker.autorouter().board();
|
|
||||||
|
|
||||||
// FIXME: I don't know how to avoid buffering the entire exported file
|
|
||||||
let mut writebuf = vec![];
|
|
||||||
|
|
||||||
design.write_ses(board, &mut writebuf);
|
|
||||||
|
|
||||||
let mut dialog = rfd::AsyncFileDialog::new();
|
|
||||||
if let Some(filename) = Path::new(design.get_name()).file_stem() {
|
|
||||||
if let Some(filename) = filename.to_str() {
|
|
||||||
dialog = dialog.set_file_name(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let task = dialog
|
|
||||||
.add_filter(tr.text("specctra-session-file"), &["ses"])
|
|
||||||
.save_file();
|
|
||||||
|
|
||||||
execute(async move {
|
|
||||||
if let Some(file_handle) = task.await {
|
|
||||||
file_handle.write(&writebuf).await;
|
|
||||||
ctx.request_repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if import_history.consume_key_triggered(ctx, ui) {
|
|
||||||
let ctx = ctx.clone();
|
|
||||||
let task = rfd::AsyncFileDialog::new().pick_file();
|
|
||||||
|
|
||||||
execute(async move {
|
|
||||||
if let Some(file_handle) = task.await {
|
|
||||||
let file_sender = FileSender::new(history_sender);
|
|
||||||
file_sender.send(file_handle).await;
|
|
||||||
ctx.request_repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if export_history.consume_key_triggered(ctx, ui) {
|
|
||||||
if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_ref() {
|
|
||||||
let ctx = ctx.clone();
|
|
||||||
let task = rfd::AsyncFileDialog::new().save_file();
|
|
||||||
|
|
||||||
// FIXME: I don't think we should be buffering everything in a `Vec<u8>`.
|
|
||||||
let mut writebuf = vec![];
|
|
||||||
serde_json::to_writer_pretty(&mut writebuf, invoker.history());
|
|
||||||
|
|
||||||
execute(async move {
|
|
||||||
if let Some(file_handle) = task.await {
|
|
||||||
file_handle.write(&writebuf).await;
|
|
||||||
ctx.request_repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if quit.consume_key_triggered(ctx, ui) {
|
|
||||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
|
||||||
} else if autoroute.consume_key_triggered(ctx, ui) {
|
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
|
||||||
}) {
|
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
|
||||||
maybe_overlay,
|
|
||||||
) {
|
|
||||||
let selection = overlay.selection().clone();
|
|
||||||
overlay.clear_selection();
|
|
||||||
maybe_activity.insert(ActivityWithStatus::new_execute(
|
|
||||||
invoker.execute_stepper(Command::Autoroute(
|
|
||||||
selection.pin_selection,
|
|
||||||
self.autorouter_options,
|
|
||||||
))?,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) {
|
|
||||||
} else if remove_bands.consume_key_triggered(ctx, ui) {
|
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
|
||||||
}) {
|
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
|
||||||
maybe_overlay,
|
|
||||||
) {
|
|
||||||
let selection = overlay.selection().clone();
|
|
||||||
overlay.clear_selection();
|
|
||||||
maybe_activity.insert(ActivityWithStatus::new_execute(
|
|
||||||
invoker.execute_stepper(Command::RemoveBands(
|
|
||||||
selection.band_selection,
|
|
||||||
))?,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if measure_length.consume_key_triggered(ctx, ui) {
|
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
|
||||||
}) {
|
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
|
||||||
maybe_overlay,
|
|
||||||
) {
|
|
||||||
let selection = overlay.selection().clone();
|
|
||||||
overlay.clear_selection();
|
|
||||||
maybe_activity.insert(ActivityWithStatus::new_execute(
|
|
||||||
invoker.execute_stepper(Command::MeasureLength(
|
|
||||||
selection.band_selection,
|
|
||||||
))?,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if undo.consume_key_triggered(ctx, ui) {
|
|
||||||
if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_mut() {
|
|
||||||
invoker.undo();
|
|
||||||
}
|
|
||||||
} else if redo.consume_key_triggered(ctx, ui) {
|
|
||||||
if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_mut() {
|
|
||||||
invoker.redo();
|
|
||||||
}
|
|
||||||
} else if compare_detours.consume_key_triggered(ctx, ui) {
|
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
|
||||||
}) {
|
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
|
||||||
maybe_overlay,
|
|
||||||
) {
|
|
||||||
let selection = overlay.selection().clone();
|
|
||||||
overlay.clear_selection();
|
|
||||||
maybe_activity.insert(ActivityWithStatus::new_execute(
|
|
||||||
invoker.execute_stepper(Command::CompareDetours(
|
|
||||||
selection.pin_selection,
|
|
||||||
self.autorouter_options,
|
|
||||||
))?,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok::<(), InvokerError>(())
|
|
||||||
})
|
|
||||||
.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -21,8 +21,8 @@ use topola::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
activity::ActivityWithStatus, app::execute, layers::Layers, overlay::Overlay, painter::Painter,
|
activity::ActivityWithStatus, app::execute, layers::Layers, menu_bar::MenuBar,
|
||||||
top::Top,
|
overlay::Overlay, painter::Painter,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Viewport {
|
pub struct Viewport {
|
||||||
|
|
@ -41,7 +41,7 @@ impl Viewport {
|
||||||
pub fn update(
|
pub fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &egui::Context,
|
ctx: &egui::Context,
|
||||||
top: &Top,
|
top: &MenuBar,
|
||||||
maybe_invoker: &mut Option<Invoker<SpecctraMesadata>>,
|
maybe_invoker: &mut Option<Invoker<SpecctraMesadata>>,
|
||||||
maybe_activity: &mut Option<ActivityWithStatus>,
|
maybe_activity: &mut Option<ActivityWithStatus>,
|
||||||
maybe_overlay: &mut Option<Overlay>,
|
maybe_overlay: &mut Option<Overlay>,
|
||||||
|
|
@ -66,7 +66,7 @@ impl Viewport {
|
||||||
pub fn paint(
|
pub fn paint(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &egui::Context,
|
ctx: &egui::Context,
|
||||||
top: &Top,
|
top: &MenuBar,
|
||||||
maybe_invoker: &mut Option<Invoker<SpecctraMesadata>>,
|
maybe_invoker: &mut Option<Invoker<SpecctraMesadata>>,
|
||||||
maybe_activity: &mut Option<ActivityWithStatus>,
|
maybe_activity: &mut Option<ActivityWithStatus>,
|
||||||
maybe_overlay: &mut Option<Overlay>,
|
maybe_overlay: &mut Option<Overlay>,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue