mod about;
mod chips;
mod current_command;
mod cycles;
mod editors;
mod export_modal;
mod font_warmup;
mod help;
mod icons;
mod import_modal;
mod lamps;
mod memory_list;
pub(crate) use memory_list::{operand_jump_target, operand_port_number};
mod menu;
mod menu_dropdowns;
mod menu_labels;
mod modal;
mod monitor;
mod monitor_font;
pub(crate) mod monitor_image;
mod mux;
mod network;
mod network_settings;
mod notices;
mod opcode_dropdown;
mod printer;
mod printer_setup;
mod schematic;
mod settings_dialog;
mod speed;
mod status_register;
mod storage;
mod styles;
pub(crate) mod theme;
mod tooltips;
mod utils;
mod widgets;
mod windows;
use iced::widget::{Space, column, container, mouse_area, opaque, row, stack};
use iced::{Element, Length};
use modal::discard_modal_overlay;
use monitor::monitor_window_overlay;
use network::network_window_overlay;
use notices::{error_notice_overlay, halt_notice_overlay, with_settings_saved_notice};
use printer::printer_window_overlay;
use printer_setup::with_printer_setup_overlay;
use settings_dialog::settings_modal_overlay;
use storage::{floppy_window_overlay, hdd_window_overlay};
use styles::app_style;
use about::about_modal_overlay;
use export_modal::{ExportModalViewState, export_modal_overlay};
use help::help_modal_overlay;
use import_modal::{ImportModalViewState, import_modal_overlay};
use crate::app::{DesktopApp, MenuId, Message, PendingAction};
const MENU_DROPDOWN_TOP: f32 = 34.0;
pub(super) const FILE_MENU_DROPDOWN_LEFT: f32 = 39.0;
pub(super) const MP_MENU_DROPDOWN_LEFT: f32 = 93.0;
pub(super) const VIEW_MENU_DROPDOWN_LEFT: f32 = 130.0;
pub(super) const HELP_MENU_DROPDOWN_LEFT: f32 = 308.0;
impl DesktopApp {
fn main_view(&self) -> Element<'_, Message> {
let main = row![self.schematic_panel(), self.side_panel()]
.spacing(8)
.height(Length::Fill);
let content = column![self.menu_bar(), main]
.padding(iced::Padding {
top: 0.0,
right: 8.0,
bottom: 8.0,
left: 8.0,
})
.spacing(8)
.width(Length::Fill)
.height(Length::Fill);
let app_root: Element<'_, Message> = container(content)
.width(Length::Fill)
.height(Length::Fill)
.style(app_style)
.into();
let app_root = font_warmup::wrap_startup(self.startup_frames_seen, app_root);
let app_with_menu: Element<'_, Message> = if let Some(dropdown) = self.menu_dropdown() {
let left = match self.open_menu {
Some(MenuId::File) => FILE_MENU_DROPDOWN_LEFT,
Some(MenuId::Mp) => MP_MENU_DROPDOWN_LEFT,
Some(MenuId::View) => VIEW_MENU_DROPDOWN_LEFT,
Some(MenuId::Help) => HELP_MENU_DROPDOWN_LEFT,
Some(MenuId::Settings) | None => FILE_MENU_DROPDOWN_LEFT,
};
stack![app_root, menu_dropdown_overlay(dropdown, left)]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else {
app_root
};
let app_with_overlays: Element<'_, Message> =
if let Some(notice) = self.halt_notice.as_deref() {
stack![app_with_menu, halt_notice_overlay(notice)]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else {
app_with_menu
};
let app_with_overlays: Element<'_, Message> =
if let Some(notice) = self.error_notice.as_deref() {
stack![app_with_overlays, error_notice_overlay(notice)]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else {
app_with_overlays
};
let scrimmed: Element<'_, Message> = if self.opcode_dropdown_address.is_some() {
mouse_area(app_with_overlays)
.on_press(Message::HideOpcodeDropdown)
.into()
} else if self.open_menu.is_some() {
mouse_area(app_with_overlays)
.on_press(Message::MenuClosed)
.into()
} else {
app_with_overlays
};
let layered: Element<'_, Message> = if let Some(action) = self.pending_action.as_ref() {
let modal = discard_modal_overlay(
action,
self.discard_modal_focus,
self.discard_modal_keyboard_focus_visible,
self.lang,
);
if matches!(action, PendingAction::DeleteHdd)
&& self.hdd_open
&& !self.hdd_window.detached
{
stack![
scrimmed,
hdd_window_overlay(
&self.snapshot.devices.hdd,
self.hdd_file_exists,
self.hdd_show_image_contents,
&self.hdd_image_contents,
self.hdd_image_error.as_deref(),
self.lang,
),
modal,
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else {
stack![scrimmed, modal]
.width(Length::Fill)
.height(Length::Fill)
.into()
}
} else if self.export_modal_open {
stack![
scrimmed,
export_modal_overlay(ExportModalViewState {
tab: self.export_tab,
target_input: self.export_target_input(),
target_options: self.export_target_options(),
target_dropdown_open: self.export_target_dropdown_open,
target_highlight: self.export_target_highlight,
memory_start: &self.export_memory_start_input,
memory_end: &self.export_memory_end_input,
columns: self.export_memory_columns,
registers: self.export_registers,
flags: self.export_flags,
lang: self.lang,
})
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if self.import_modal_open {
stack![
scrimmed,
import_modal_overlay(ImportModalViewState {
file_display: &self.import_file_display,
format: self.import_file_format,
target_input: &self.import_target_input,
target_options: &self.import_target_options,
target_dropdown_open: self.import_target_dropdown_open,
target_highlight: self.import_target_highlight,
target_scroll_reveal: self.import_target_scroll_visible_ticks > 0,
error: self.import_error.as_deref(),
lang: self.lang,
})
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if let Some(dialog) = self.settings_dialog.as_ref() {
stack![
scrimmed,
settings_modal_overlay(dialog, self.lang, self.file_association_toggle_revision)
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if self.about_dialog_open {
stack![scrimmed, about_modal_overlay(self.lang)]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if let Some(dialog) = self.help_dialog.as_ref() {
stack![scrimmed, help_modal_overlay(dialog, self.lang)]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if self.monitor_open && !self.monitor_window.detached {
stack![
scrimmed,
monitor_window_overlay(
&self.snapshot.devices.monitor,
self.monitor_split,
self.monitor_hex_popup,
self.monitor_hex_filter,
self.monitor_hex_scroll_visible_ticks > 0,
self.lang
)
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if self.hdd_open && !self.hdd_window.detached {
stack![
scrimmed,
hdd_window_overlay(
&self.snapshot.devices.hdd,
self.hdd_file_exists,
self.hdd_show_image_contents,
&self.hdd_image_contents,
self.hdd_image_error.as_deref(),
self.lang,
)
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if self.floppy_open && !self.floppy_window.detached {
stack![
scrimmed,
floppy_window_overlay(
&self.snapshot.devices.floppy,
self.floppy_show_image_contents,
&self.floppy_image_contents,
self.floppy_image_error.as_deref(),
self.lang
)
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if self.network_open && !self.network_window.detached {
stack![scrimmed, network_window_overlay(self.network_view_state())]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else if self.printer_open && !self.printer_window.detached {
stack![
scrimmed,
printer_window_overlay(
&self.snapshot.devices.printer,
self.printer_text_view,
self.printer_target_label(),
self.lang
)
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else {
scrimmed
};
with_settings_saved_notice(
with_printer_setup_overlay(
layered,
self.printer_setup_dialog
.as_ref()
.filter(|_| !self.printer_setup_uses_detached_window()),
self.lang,
),
self.settings_saved_notice,
self.lang,
)
}
}
fn menu_dropdown_overlay(dropdown: Element<'_, Message>, left: f32) -> Element<'_, Message> {
column![
Space::new().height(Length::Fixed(MENU_DROPDOWN_TOP)),
row![
Space::new().width(Length::Fixed(left)),
opaque(dropdown),
Space::new().width(Length::Fill),
]
.width(Length::Fill),
]
.width(Length::Fill)
.height(Length::Fill)
.into()
}