hardware_toolkit/src/ui/main_window.rs

252 lines
7.5 KiB
Rust
Raw Normal View History

use crate::ui::db_browser::DbBrowserMsg;
use crate::ui::home_page::HomePage;
use crate::ui::home_page::HomePageMsg;
use crate::ui::jlc_downloader::JlcDownloaderMsg;
use crate::ui::part_viewer::PartViewerMsg;
2025-06-28 16:43:09 +08:00
use iced::Subscription;
use iced::Task;
use tracing::info;
use tracing::warn;
#[allow(unused_imports)]
use super::db_browser;
#[allow(unused_imports)]
use super::home_page;
#[allow(unused_imports)]
use super::jlc_downloader;
#[allow(unused_imports)]
use super::part_viewer;
use iced::Theme;
#[allow(unused_imports)]
use iced::widget as w;
use iced::widget::button;
use iced::widget::row;
#[allow(unused_imports)]
use iced::{
Element, Length,
alignment::{Horizontal, Vertical},
widget::{Column, Container, Text, column},
};
use std::fmt::Display;
#[allow(dead_code)]
struct MainWindow {
title: String,
theme: iced::Theme,
curr_tab: TabId,
home_page: crate::ui::home_page::HomePage,
jlc_downloader: crate::ui::jlc_downloader::JlcDownloader,
db_browser: crate::ui::db_browser::DbBrowser,
part_viewer: crate::ui::part_viewer::PartViewer,
}
impl Default for MainWindow {
fn default() -> Self {
let mut home_page = HomePage::default();
let mut theme = Theme::default();
if let Ok(saved_theme) = crate::utils::app_settings::get_curr_theme() {
theme = Theme::ALL[saved_theme as usize % Theme::ALL.len()].clone();
home_page.theme = theme.clone();
}
Self {
title: "HardwareToolkit".into(),
theme,
curr_tab: Default::default(),
home_page,
jlc_downloader: Default::default(),
db_browser: Default::default(),
part_viewer: Default::default(),
}
}
}
2025-06-28 16:43:09 +08:00
impl MainWindow {
pub fn new() -> (Self, Task<MainWindowMsg>) {
(
Self::default(),
Task::batch([
iced::widget::focus_next(),
]),
)
}
}
pub fn main_window() {
2025-06-28 16:43:09 +08:00
let _ = iced::application(MainWindow::new, MainWindow::update, MainWindow::view)
.theme(MainWindow::theme)
.default_font(iced::Font::with_name("微软雅黑"))
.title(MainWindow::title)
2025-06-28 16:43:09 +08:00
.subscription(MainWindow::subscription)
.run();
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub enum MainWindowMsg {
ThemeChanged(iced::Theme),
2025-06-28 16:43:09 +08:00
SearchKeywordChanged(String),
TitleChanged(String),
TabSelected(TabId),
HomePage(HomePageMsg),
JlcDownloader(JlcDownloaderMsg),
DbBrowser(DbBrowserMsg),
PartViewer(PartViewerMsg),
Nothing,
}
2025-06-28 16:43:09 +08:00
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum TabId {
HomePage,
JlcDownloader,
DbBrowser,
PartViewer,
}
2025-06-28 16:43:09 +08:00
impl Default for TabId {
fn default() -> Self {
if let Ok(tab) = crate::utils::app_settings::get_curr_page() {
Self::from(tab)
} else {
Self::HomePage
}
}
}
impl TabId {
pub fn save(&self) {
let v = *self;
match crate::utils::app_settings::set_curr_page(v.into()) {
Ok(_) => {}
Err(_) => {
warn!("Failed to save the current page.");
}
}
}
}
impl Display for TabId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
TabId::HomePage => "主页",
TabId::JlcDownloader => "3D模型下载",
TabId::DbBrowser => "数据库浏览",
TabId::PartViewer => "元件查看",
}
)
}
}
2025-06-28 16:43:09 +08:00
impl From<TabId> for u32 {
fn from(val: TabId) -> Self {
match val {
TabId::HomePage => 0,
TabId::JlcDownloader => 1,
TabId::DbBrowser => 2,
TabId::PartViewer => 3,
}
}
}
impl From<u32> for TabId {
fn from(value: u32) -> Self {
match value {
0 => Self::HomePage,
1 => Self::JlcDownloader,
2 => Self::DbBrowser,
3 => Self::PartViewer,
_ => Self::HomePage,
}
}
}
impl MainWindow {
fn title(&self) -> String {
self.title.clone()
}
fn theme(&self) -> Theme {
self.theme.clone()
}
2025-06-28 16:43:09 +08:00
fn subscription(&self) -> Subscription<MainWindowMsg> {
info!("subscription run once.");
iced::keyboard::on_key_press(|key, modifiers| {
info!("Press the key: {key:?}");
info!("The modifiers: {modifiers:?}");
Some(MainWindowMsg::Nothing)
})
2025-06-28 16:43:09 +08:00
}
fn create_tab_btn(&self, tab: TabId) -> Element<'_, MainWindowMsg> {
let btn_style = if self.curr_tab == tab {
button::danger
} else {
button::primary
};
let txt = format!("{tab}");
let txt = iced::widget::text(txt);
let btn = button(txt).style(btn_style);
2025-06-28 16:43:09 +08:00
btn.on_press(MainWindowMsg::TabSelected(tab)).into()
}
fn update(&mut self, msg: MainWindowMsg) -> Task<MainWindowMsg> {
2025-06-28 16:43:09 +08:00
info!("Process the msg: {msg:?}");
match msg {
MainWindowMsg::ThemeChanged(theme) => {
self.theme = theme.clone();
if let Some(idx) = Theme::ALL.iter().position(|x| x == &theme) {
crate::utils::app_settings::set_curr_theme(idx as u32).unwrap();
}
Task::none()
}
MainWindowMsg::TitleChanged(title) => {
self.title = title;
Task::none()
}
MainWindowMsg::Nothing => {
2025-06-28 16:43:09 +08:00
info!("Nothing");
iced::debug::time("Test".to_owned());
Task::none()
}
MainWindowMsg::TabSelected(i) => {
self.curr_tab = i;
2025-06-28 16:43:09 +08:00
self.curr_tab.save();
Task::none()
}
MainWindowMsg::HomePage(msg) => {
2025-06-28 16:43:09 +08:00
info!("update HomePage");
self.home_page.update(msg)
2025-06-28 16:43:09 +08:00
}
MainWindowMsg::JlcDownloader(msg) => self.jlc_downloader.update(msg),
MainWindowMsg::DbBrowser(msg) => self.db_browser.update(msg),
MainWindowMsg::PartViewer(part_viewer_msg) => self.part_viewer.update(part_viewer_msg),
MainWindowMsg::SearchKeywordChanged(k) => self
.jlc_downloader
.update(JlcDownloaderMsg::KeywordChanged(k)),
}
}
fn view(&self) -> Element<'_, MainWindowMsg> {
let h = row![
self.create_tab_btn(TabId::HomePage),
self.create_tab_btn(TabId::JlcDownloader),
self.create_tab_btn(TabId::DbBrowser),
self.create_tab_btn(TabId::PartViewer)
];
let v = match self.curr_tab {
TabId::HomePage => self.home_page.view(),
TabId::JlcDownloader => self.jlc_downloader.view(),
TabId::DbBrowser => self.db_browser.view(),
TabId::PartViewer => self.part_viewer.view(),
};
// let content = iced::widget::Button::new("Click").on_press(MainWindowMsg::Nothing);
column![h, v].into()
}
}
pub trait TabContent {
type TabMessage;
fn update(&mut self, msg: Self::TabMessage) -> Task<MainWindowMsg>;
fn view(&self) -> Element<'_, MainWindowMsg> {
iced::widget::Container::new(self.content())
.width(Length::Fill)
.height(Length::Fill)
.align_x(Horizontal::Left)
.align_y(Vertical::Top)
.padding(16.0)
.into()
}
fn content(&self) -> Element<'_, MainWindowMsg>;
}