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 schematic;
mod settings_dialog;
mod speed;
mod status_register;
mod storage;
mod styles;
mod theme;
mod tooltips;
mod utils;
mod widgets;
use iced::widget::{Space, column, container, mouse_area, opaque, row, stack};
use iced::{Element, Length};
use modal::discard_modal_overlay;
use monitor::{monitor_window, monitor_window_overlay};
use network::{NetworkViewState, network_window, network_window_overlay};
use notices::{error_notice_overlay, halt_notice_overlay};
use printer::{printer_window, printer_window_overlay};
use settings_dialog::settings_modal_overlay;
use storage::{floppy_window, floppy_window_overlay, hdd_window, 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 network_view_state(&self) -> NetworkViewState<'_> {
NetworkViewState {
network: &self.snapshot.devices.network,
settings_open: self.network_settings_open,
text_view: self.network_text_view,
mode: self.network_mode_draft,
host: &self.network_host_input,
port: &self.network_port_input,
error: self.network_settings_error.as_deref(),
lang: self.lang,
}
}
pub(crate) fn view(&self, window: iced::window::Id) -> Element<'_, Message> {
if self.monitor_window.id == Some(window) {
if !self.monitor_window.detached {
return Space::new().into();
}
return monitor_window(
&self.snapshot.devices.monitor,
self.monitor_split,
self.monitor_hex_popup,
self.monitor_hex_filter,
self.monitor_hex_scroll_visible_ticks > 0,
self.monitor_window.always_on_top,
self.lang,
);
}
if self.floppy_window.id == Some(window) {
if !self.floppy_window.detached {
return Space::new().into();
}
return floppy_window(
&self.snapshot.devices.floppy,
self.floppy_show_image_contents,
&self.floppy_image_contents,
self.floppy_image_error.as_deref(),
self.floppy_window.always_on_top,
self.lang,
);
}
if self.hdd_window.id == Some(window) {
if !self.hdd_window.detached {
return Space::new().into();
}
return hdd_window(
&self.snapshot.devices.hdd,
self.hdd_file_exists,
self.hdd_show_image_contents,
&self.hdd_image_contents,
self.hdd_image_error.as_deref(),
self.hdd_window.always_on_top,
self.lang,
);
}
if self.network_window.id == Some(window) {
if !self.network_window.detached {
return Space::new().into();
}
return network_window(self.network_view_state(), self.network_window.always_on_top);
}
if self.printer_window.id == Some(window) {
if !self.printer_window.detached {
return Space::new().into();
}
return printer_window(
&self.snapshot.devices.printer,
self.printer_text_view,
self.printer_window.always_on_top,
self.lang,
);
}
if self.main_window_id != Some(window) {
return Space::new().into();
}
self.main_view()
}
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,
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
};
if let Some(action) = self.pending_action.as_ref() {
let modal = discard_modal_overlay(action, self.discard_modal_focus, 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.lang
)
]
.width(Length::Fill)
.height(Length::Fill)
.into()
} else {
scrimmed
}
}
}
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()
}