mod keyboard;
use super::tasks::load_native_printer_configuration_blocking;
use super::{PrinterSetupDialog, PrinterSetupError, PrinterSetupTarget};
use crate::app::{DesktopApp, Message};
use iced::Task;
use k580_ui::devices::printer::{PrinterConfiguration, PrinterInfo, PrinterSettings};
impl DesktopApp {
pub(crate) fn route_printer_setup_message(
&mut self,
message: &Message,
) -> Option<Task<Message>> {
self.printer_setup_dialog.as_ref()?;
if let Message::PrinterSetupWindowPositionLoaded(position) = message {
return Some(self.open_detached_printer_setup_window(*position));
}
if self
.printer_setup_dialog
.as_ref()
.is_some_and(|dialog| dialog.properties.is_some())
{
return self.route_printer_properties_message(message);
}
match message {
Message::PrinterSetupLoaded(result) => {
Some(self.finish_printer_setup_load(result.clone()))
}
Message::PrinterSetupSelected(name) => {
if let Some(dialog) = self.printer_setup_dialog.as_mut() {
dialog.selected_name = Some(name.clone());
dialog.configuration = None;
dialog.error = None;
dialog.open_dropdown = None;
dialog.dropdown_highlight = None;
}
Some(self.load_selected_printer_configuration())
}
Message::PrinterSetupDropdownToggled(dropdown) => {
self.toggle_printer_setup_dropdown(*dropdown);
Some(Task::none())
}
Message::PrinterSetupDropdownDismissed(dropdown) => {
if self
.printer_setup_dialog
.as_ref()
.is_some_and(|dialog| dialog.open_dropdown == Some(*dropdown))
{
self.close_printer_setup_dropdown();
}
Some(Task::none())
}
Message::PrinterSetupConfigurationLoaded {
printer_name,
result,
} => {
self.finish_printer_configuration_load(printer_name, result.clone());
Some(Task::none())
}
Message::PrinterSetupPaperSelected(id) => {
self.close_printer_setup_dropdown();
self.select_printer_paper(*id);
Some(Task::none())
}
Message::PrinterSetupSourceSelected(id) => {
self.close_printer_setup_dropdown();
self.select_printer_source(*id);
Some(Task::none())
}
Message::PrinterSetupOrientationSelected(orientation) => {
self.close_printer_setup_dropdown();
if let Some(settings) = self
.printer_setup_dialog
.as_mut()
.and_then(|dialog| dialog.configuration.as_mut())
.map(|configuration| &mut configuration.settings)
{
settings.orientation = *orientation;
}
Some(Task::none())
}
Message::PrinterSetupProperties => Some(self.open_selected_printer_properties()),
Message::PrinterSetupConfirmed => {
let close = self.close_detached_printer_setup_window();
self.confirm_printer_setup_dialog();
Some(close)
}
Message::ClosePrinterSetup => {
let close = self.close_detached_printer_setup_window();
self.close_printer_setup_dialog();
Some(close)
}
Message::EscPressed => {
if self
.printer_setup_dialog
.as_ref()
.is_some_and(|dialog| dialog.open_dropdown.is_some())
{
self.close_printer_setup_dropdown();
} else {
let close = self.close_detached_printer_setup_window();
self.close_printer_setup_dialog();
return Some(close);
}
Some(Task::none())
}
Message::EnterPressed => Some(self.activate_printer_setup_focus()),
Message::FocusCycle { backward } => {
self.cycle_printer_setup_focus(*backward);
Some(Task::none())
}
Message::ArrowKey(direction) => {
self.move_printer_setup_dropdown_highlight(*direction);
Some(Task::none())
}
Message::MousePressed | Message::MousePressedIgnored => {
if let Some(dialog) = self.printer_setup_dialog.as_mut() {
dialog.focus_visible = false;
}
if matches!(message, Message::MousePressedIgnored) {
self.close_printer_setup_dropdown();
}
Some(Task::none())
}
Message::Tick
| Message::CursorMoved(_)
| Message::ModifiersChanged(_)
| Message::FocusReconciled { .. }
| Message::ResolveFocusedTracker(_) => None,
_ => Some(Task::none()),
}
}
fn finish_printer_setup_load(
&mut self,
result: Result<Vec<PrinterInfo>, String>,
) -> Task<Message> {
let Some(dialog) = self.printer_setup_dialog.as_mut() else {
return Task::none();
};
dialog.loading = false;
match result {
Ok(printers) => {
dialog.error = printers.is_empty().then_some(PrinterSetupError::NoPrinters);
dialog.printers = printers;
if !selected_printer_exists(dialog) {
dialog.selected_name = default_printer_name(dialog)
.or_else(|| dialog.printers.first().map(|printer| printer.name.clone()));
}
}
Err(error) => {
dialog.printers.clear();
dialog.selected_name = None;
dialog.error = Some(PrinterSetupError::Driver(error));
}
}
self.load_selected_printer_configuration()
}
fn load_selected_printer_configuration(&mut self) -> Task<Message> {
let Some(dialog) = self.printer_setup_dialog.as_mut() else {
return Task::none();
};
let Some(printer) = dialog.selected_printer().cloned() else {
return Task::none();
};
dialog.configuration_loading = true;
let printer_name = printer.name.clone();
Task::perform(
load_native_printer_configuration_blocking(printer),
move |result| Message::PrinterSetupConfigurationLoaded {
printer_name,
result,
},
)
}
fn finish_printer_configuration_load(
&mut self,
printer_name: &str,
result: Result<PrinterConfiguration, String>,
) {
let preferred = self.preferred_printer_settings(printer_name);
let Some(dialog) = self.printer_setup_dialog.as_mut() else {
return;
};
if dialog.selected_name.as_deref() != Some(printer_name) {
return;
}
dialog.configuration_loading = false;
match result {
Ok(mut configuration) => {
if let Some(settings) = preferred {
merge_preferred_settings(&mut configuration, settings);
}
dialog.configuration = Some(configuration);
dialog.error = None;
}
Err(error) => {
dialog.configuration = None;
dialog.error = Some(PrinterSetupError::Driver(error));
}
}
}
fn preferred_printer_settings(&self, printer_name: &str) -> Option<PrinterSettings> {
let target = self.printer_setup_dialog.as_ref()?.target;
match target {
PrinterSetupTarget::Session => self.active_printer_settings(),
PrinterSetupTarget::Settings => self
.settings_dialog
.as_ref()
.and_then(|dialog| dialog.draft_printer_settings.as_ref()),
}
.filter(|settings| settings.printer_name == printer_name)
.cloned()
}
fn select_printer_paper(&mut self, id: i16) {
let Some(configuration) = self
.printer_setup_dialog
.as_mut()
.and_then(|dialog| dialog.configuration.as_mut())
else {
return;
};
configuration.select_paper(id);
}
fn select_printer_source(&mut self, id: i16) {
let Some(configuration) = self
.printer_setup_dialog
.as_mut()
.and_then(|dialog| dialog.configuration.as_mut())
else {
return;
};
configuration.select_source(id);
}
fn confirm_printer_setup_dialog(&mut self) {
let Some(dialog) = self.printer_setup_dialog.take() else {
return;
};
self.printer_setup_pending = false;
let Some(name) = dialog.selected_name else {
return;
};
let settings = dialog
.configuration
.map(|configuration| configuration.settings)
.unwrap_or_else(|| PrinterSettings::named(name.clone()));
match dialog.target {
PrinterSetupTarget::Session => self.printer_session_settings = Some(settings),
PrinterSetupTarget::Settings => {
if let Some(settings_dialog) = self.settings_dialog.as_mut() {
settings_dialog.draft_printer_settings = Some(settings);
}
}
}
}
pub(super) fn close_printer_setup_dialog(&mut self) {
self.printer_setup_dialog = None;
self.printer_setup_pending = false;
}
}
fn selected_printer_exists(dialog: &PrinterSetupDialog) -> bool {
dialog.selected_name.as_deref().is_some_and(|selected| {
dialog
.printers
.iter()
.any(|printer| printer.name == selected)
})
}
fn default_printer_name(dialog: &PrinterSetupDialog) -> Option<String> {
dialog
.printers
.iter()
.find(|printer| printer.is_default)
.map(|printer| printer.name.clone())
}
fn merge_preferred_settings(
configuration: &mut PrinterConfiguration,
mut preferred: PrinterSettings,
) {
if preferred.devmode.is_empty() {
return;
}
if !preferred
.paper_id
.is_some_and(|id| configuration.papers.iter().any(|paper| paper.id == id))
{
preferred.paper_id = configuration.settings.paper_id;
preferred.paper_name = configuration.settings.paper_name.clone();
}
if !preferred
.source_id
.is_some_and(|id| configuration.sources.iter().any(|source| source.id == id))
{
preferred.source_id = configuration.settings.source_id;
preferred.source_name = configuration.settings.source_name.clone();
}
configuration.settings = preferred;
}