diff --git a/Cargo.toml b/Cargo.toml index a75dc77..15492bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,30 +7,10 @@ edition = "2024" iced = { git = "https://github.com/iced-rs/iced.git", features = [ "debug", "advanced", + "image", ] } tokio = { version = "1.45.1", features = ["full"] } -iced_aw = { git = "https://github.com/iced-rs/iced_aw.git", features = [ - "badge", - "card", - "number_input", - "date_picker", - "color_picker", - "grid", - "tab_bar", - "tabs", - "time_picker", - "slide_bar", - "wrap", - "selection_list", - "quad", - "context_menu", - "spinner", - "drop_down", - "menu", - "sidebar", - "labeled_frame", -] } reqwest = "0.12.20" tracing-subscriber = { version = "0.3.19", features = [ "chrono", diff --git a/src/main.rs b/src/main.rs index efc50fb..a9bef08 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ mod ui; mod utils; +mod widgets; mod winsparkle; + fn main() { tracing_subscriber::fmt::init(); ui::main_window::main_window(); diff --git a/src/ui/db_browser.rs b/src/ui/db_browser.rs index e69de29..5d1aa5d 100644 --- a/src/ui/db_browser.rs +++ b/src/ui/db_browser.rs @@ -0,0 +1,35 @@ +use iced::{Length, alignment::Horizontal, widget::Column}; + +use crate::ui::main_window::{MainWindowMsg, TabContent}; + +#[derive(Default)] +pub struct DbBrowser {} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum DbBrowserMsg { + Nothing, +} + +impl TabContent for DbBrowser { + type TabMessage = DbBrowserMsg; + + fn update(&self, msg: Self::TabMessage) { + match msg { + DbBrowserMsg::Nothing => { + println!("This function not allowed"); + } + } + } + + fn content(&self) -> iced::Element<'_, MainWindowMsg> { + let btn = iced::widget::button("DbBrowser") + .on_press(MainWindowMsg::DbBrowser(DbBrowserMsg::Nothing)); + + Column::new() + .align_x(Horizontal::Left) + .width(Length::Fill) + .height(Length::Fill) + .push(btn) + .into() + } +} diff --git a/src/ui/home_page.rs b/src/ui/home_page.rs index e48d136..a6bd0e6 100644 --- a/src/ui/home_page.rs +++ b/src/ui/home_page.rs @@ -1,52 +1,36 @@ -use iced::{ - Alignment, Element, - alignment::{Horizontal, Vertical}, - widget::{Column, Container}, -}; +use iced::{Length, alignment::Horizontal, widget::Column}; -use crate::ui::main_window::{MainWindowMsg, TabFrame}; +#[allow(unused_imports)] +use crate::ui::main_window::{MainWindowMsg, TabContent}; + +#[derive(Default)] pub struct HomePage {} - -impl Default for HomePage { - fn default() -> Self { - Self {} - } +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub enum HomePageMsg { + #[default] + Nothing, } -impl HomePage { - pub fn update(&mut self, msg: HomePageMsg) { + +impl TabContent for HomePage { + fn content(&self) -> iced::Element<'_, MainWindowMsg> { + let btn = iced::widget::button("HomePage") + .on_press(MainWindowMsg::HomePage(HomePageMsg::Nothing)); + + Column::new() + .align_x(Horizontal::Left) + .width(Length::Fill) + .height(Length::Fill) + .push(btn) + .into() + } + + type TabMessage = HomePageMsg; + + fn update(&self, msg: Self::TabMessage) { match msg { HomePageMsg::Nothing => { - println!("HomePage::Message::Nothing"); + println!("This way ok."); } } } } - -#[derive(Debug, Clone)] -pub enum HomePageMsg { - Nothing, -} - -impl TabFrame for HomePage { - type Message = MainWindowMsg; - - fn title(&self) -> String { - "HomePage".to_owned() - } - - fn tab_label(&self) -> iced_aw::TabLabel { - iced_aw::TabLabel::Text("HomePage".to_owned()) - } - - fn container(&self) -> iced::Element<'_, Self::Message> { - let content: Element<'_, HomePageMsg> = Container::new( - Column::new() - .align_x(Alignment::Center) - .push(iced::widget::button("Homepage Button").on_press(HomePageMsg::Nothing)), - ) - .align_x(Horizontal::Center) - .align_y(Vertical::Center) - .into(); - content.map(MainWindowMsg::HomePageMsg) - } -} diff --git a/src/ui/jlc_downloader.rs b/src/ui/jlc_downloader.rs index 526f4a8..e7feaf4 100644 --- a/src/ui/jlc_downloader.rs +++ b/src/ui/jlc_downloader.rs @@ -1,13 +1,34 @@ -use iced::{ - Alignment, Element, - alignment::{Horizontal, Vertical}, - widget::{Column, Container}, -}; +use iced::{Length, alignment::Horizontal, widget::Column}; -use crate::ui::main_window::{MainWindowMsg, TabFrame}; +use crate::ui::main_window::{MainWindowMsg, TabContent}; +#[derive(Default)] pub struct JlcDownloader {} - +#[derive(Debug, Clone, Eq, PartialEq)] pub enum JlcDownloaderMsg { Nothing, } + +impl TabContent for JlcDownloader { + type TabMessage = JlcDownloaderMsg; + + fn update(&self, msg: Self::TabMessage) { + match msg { + JlcDownloaderMsg::Nothing => { + println!("JlcDownloaderMsg::Nothing"); + } + } + } + + fn content(&self) -> iced::Element<'_, MainWindowMsg> { + let btn = iced::widget::button("JlcDownloader") + .on_press(MainWindowMsg::JlcDownloader(JlcDownloaderMsg::Nothing)); + + Column::new() + .align_x(Horizontal::Left) + .width(Length::Fill) + .height(Length::Fill) + .push(btn) + .into() + } +} diff --git a/src/ui/main_window.rs b/src/ui/main_window.rs index 3c5fbc8..7ff838e 100644 --- a/src/ui/main_window.rs +++ b/src/ui/main_window.rs @@ -1,70 +1,135 @@ +use crate::ui::db_browser::DbBrowserMsg; +use crate::ui::home_page::HomePageMsg; +use crate::ui::jlc_downloader::JlcDownloaderMsg; +use crate::ui::part_viewer::PartViewerMsg; + +#[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::button::Status; +use iced::widget::button::Style; +use iced::widget::row; +#[allow(unused_imports)] use iced::{ Element, Length, alignment::{Horizontal, Vertical}, - widget::{Column, Container, Text}, + widget::{Column, Container, Text, column}, }; -use iced_aw::Tabs; -use iced_aw::iced_fonts; +use std::fmt::Display; +#[allow(dead_code)] struct MainWindow { title: String, theme: iced::Theme, curr_tab: TabId, - tab_pos: iced_aw::tabs::TabBarPosition, - home_page: home_page::HomePage, + tabs: Vec, + 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 { Self { - title: Default::default(), + title: "HardwareToolkit".into(), theme: Default::default(), curr_tab: Default::default(), - tab_pos: iced_aw::tabs::TabBarPosition::Top, home_page: Default::default(), + jlc_downloader: Default::default(), + tabs: Vec::new(), + db_browser: Default::default(), + part_viewer: Default::default(), } } } -const ICON_BYTES: &[u8] = include_bytes!("./../../fonts/icons.ttf"); -const ICON: iced::Font = iced::Font::with_name("icons"); - pub fn main_window() { - iced::application(MainWindow::default, MainWindow::update, MainWindow::view) + let _ = iced::application(MainWindow::default, MainWindow::update, MainWindow::view) + .default_font(iced::Font::with_name("微软雅黑")) .title(MainWindow::title) - .font(iced_fonts::REQUIRED_FONT_BYTES) - .font(ICON_BYTES) .run(); } +#[allow(dead_code)] #[derive(Debug, Clone)] pub enum MainWindowMsg { - TabSelected(TabId), - TabClosed(TabId), ThemeChanged(iced::Theme), TitleChanged(String), - HomePageMsg(home_page::HomePageMsg), + TabSelected(TabId), + HomePage(HomePageMsg), + JlcDownloader(JlcDownloaderMsg), + DbBrowser(DbBrowserMsg), + PartViewer(PartViewerMsg), Nothing, } +#[allow(dead_code)] #[derive(Debug, Default, Clone, PartialEq, Eq)] -enum TabId { +pub(crate) enum TabId { #[default] HomePage, JlcDownloader, DbBrowser, PartViewer, } - +#[allow(dead_code)] +struct TabItem { + pub id: TabId, + content: Box Element<'static, MainWindowMsg>>, +} +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 => "元件查看", + } + ) + } +} +fn btn_active_style(_theme: &Theme, _status: Status) -> Style { + let mut s = Style::default(); + let bgcolor = iced::Color::from_rgba8(30, 200, 200, 1.0); + s.background = Some(iced::Background::Color(bgcolor)); + s +} +fn btn_deactive_style(_theme: &Theme, _status: Status) -> Style { + let mut s = Style::default(); + let bgcolor = iced::Color::from_rgba8(220, 200, 100, 1.0); + s.background = Some(iced::Background::Color(bgcolor)); + s +} impl MainWindow { fn title(&self) -> String { self.title.clone() } + fn create_tab_btn(&self, tab: TabId) -> Element<'_, MainWindowMsg> { + let bstyle = if self.curr_tab == tab { + btn_active_style + } else { + btn_deactive_style + }; + let txt = format!("{tab}"); + + let txt = iced::widget::text(txt); + let btn = button(txt).style(bstyle); + btn.on_press(MainWindowMsg::TabSelected(tab.clone())).into() + } fn update(&mut self, msg: MainWindowMsg) { + println!("Process the msg: {msg:?}"); match msg { MainWindowMsg::ThemeChanged(theme) => { self.theme = theme; @@ -76,44 +141,53 @@ impl MainWindow { println!("Nothing"); iced::debug::time("Test".to_owned()); } - MainWindowMsg::HomePageMsg(message) => { - self.home_page.update(message); + MainWindowMsg::TabSelected(i) => { + self.curr_tab = i; } - MainWindowMsg::TabSelected(tab_id) => { - self.curr_tab = tab_id; + MainWindowMsg::HomePage(msg) => { + println!("update HomePage"); + self.home_page.update(msg); + } + 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::TabClosed(tab_id) => todo!(), } } fn view(&self) -> Element<'_, MainWindowMsg> { - let t = Tabs::new(MainWindowMsg::TabSelected) - .tab_icon_position(iced_aw::tabs::Position::Left) - .on_close(MainWindowMsg::TabClosed) - .push( - TabId::HomePage, - self.home_page.tab_label(), - self.home_page.view(), - ) - .set_active_tab(&self.curr_tab) - .icon_font(ICON) - .tab_bar_style(Box::new(iced_aw::style::tab_bar::primary)) - .tab_bar_position(self.tab_pos.clone()); - w::button("ClickMe").on_press(MainWindowMsg::Nothing).into() + 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 TabFrame { - type Message; - fn title(&self) -> String; - fn tab_label(&self) -> iced_aw::TabLabel; - fn container(&self) -> Element<'_, Self::Message>; - fn view(&self) -> Element<'_, Self::Message> { - w::Container::new(self.container()) +pub trait TabContent { + type TabMessage; + fn update(&self, msg: Self::TabMessage); + 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(5) + .padding(16.0) .into() } + fn content(&self) -> Element<'_, MainWindowMsg>; } diff --git a/src/ui/part_viewer.rs b/src/ui/part_viewer.rs index e69de29..a844e2c 100644 --- a/src/ui/part_viewer.rs +++ b/src/ui/part_viewer.rs @@ -0,0 +1,35 @@ +use iced::{Length, alignment::Horizontal, widget::Column}; + +use crate::ui::main_window::{MainWindowMsg, TabContent}; + +#[derive(Default)] +pub struct PartViewer {} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum PartViewerMsg { + Nothing, +} + +impl TabContent for PartViewer { + type TabMessage = PartViewerMsg; + + fn update(&self, msg: Self::TabMessage) { + match msg { + PartViewerMsg::Nothing => { + println!("This function not allowed."); + } + } + } + + fn content(&self) -> iced::Element<'_, MainWindowMsg> { + let btn = iced::widget::button("PartViewer") + .on_press(MainWindowMsg::PartViewer(PartViewerMsg::Nothing)); + + Column::new() + .align_x(Horizontal::Left) + .width(Length::Fill) + .height(Length::Fill) + .push(btn) + .into() + } +} diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index e69de29..cb723e7 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -0,0 +1 @@ +pub mod tab_header; diff --git a/src/widgets/tab_header.rs b/src/widgets/tab_header.rs new file mode 100644 index 0000000..c61ec73 --- /dev/null +++ b/src/widgets/tab_header.rs @@ -0,0 +1,4 @@ +#[allow(unused_imports)] +use iced::advanced::renderer; +#[allow(unused_imports)] +use iced::advanced::widget::{self, Widget};