draw some ui

这个ui框架是真tm难用,但是界面也是真的挺好看,省去了后期美化的过程,就当吃屎了吧
This commit is contained in:
z_lenovo 2025-06-23 21:52:45 +08:00
parent 117ae5df3c
commit 21353af9e4
9 changed files with 251 additions and 115 deletions

View File

@ -7,30 +7,10 @@ edition = "2024"
iced = { git = "https://github.com/iced-rs/iced.git", features = [ iced = { git = "https://github.com/iced-rs/iced.git", features = [
"debug", "debug",
"advanced", "advanced",
"image",
] } ] }
tokio = { version = "1.45.1", features = ["full"] } 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" reqwest = "0.12.20"
tracing-subscriber = { version = "0.3.19", features = [ tracing-subscriber = { version = "0.3.19", features = [
"chrono", "chrono",

View File

@ -1,6 +1,8 @@
mod ui; mod ui;
mod utils; mod utils;
mod widgets;
mod winsparkle; mod winsparkle;
fn main() { fn main() {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
ui::main_window::main_window(); ui::main_window::main_window();

View File

@ -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()
}
}

View File

@ -1,52 +1,36 @@
use iced::{ use iced::{Length, alignment::Horizontal, widget::Column};
Alignment, Element,
alignment::{Horizontal, Vertical},
widget::{Column, Container},
};
use crate::ui::main_window::{MainWindowMsg, TabFrame}; #[allow(unused_imports)]
use crate::ui::main_window::{MainWindowMsg, TabContent};
#[derive(Default)]
pub struct HomePage {} pub struct HomePage {}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
impl Default for HomePage { pub enum HomePageMsg {
fn default() -> Self { #[default]
Self {} 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 { match msg {
HomePageMsg::Nothing => { 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)
}
}

View File

@ -1,13 +1,34 @@
use iced::{ use iced::{Length, alignment::Horizontal, widget::Column};
Alignment, Element,
alignment::{Horizontal, Vertical},
widget::{Column, Container},
};
use crate::ui::main_window::{MainWindowMsg, TabFrame}; use crate::ui::main_window::{MainWindowMsg, TabContent};
#[derive(Default)]
pub struct JlcDownloader {} pub struct JlcDownloader {}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum JlcDownloaderMsg { pub enum JlcDownloaderMsg {
Nothing, 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()
}
}

View File

@ -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; use super::db_browser;
#[allow(unused_imports)]
use super::home_page; use super::home_page;
#[allow(unused_imports)]
use super::jlc_downloader; use super::jlc_downloader;
#[allow(unused_imports)]
use super::part_viewer; use super::part_viewer;
use iced::Theme;
#[allow(unused_imports)]
use iced::widget as w; 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::{ use iced::{
Element, Length, Element, Length,
alignment::{Horizontal, Vertical}, alignment::{Horizontal, Vertical},
widget::{Column, Container, Text}, widget::{Column, Container, Text, column},
}; };
use iced_aw::Tabs; use std::fmt::Display;
use iced_aw::iced_fonts;
#[allow(dead_code)]
struct MainWindow { struct MainWindow {
title: String, title: String,
theme: iced::Theme, theme: iced::Theme,
curr_tab: TabId, curr_tab: TabId,
tab_pos: iced_aw::tabs::TabBarPosition, tabs: Vec<TabItem>,
home_page: home_page::HomePage, 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 { impl Default for MainWindow {
fn default() -> Self { fn default() -> Self {
Self { Self {
title: Default::default(), title: "HardwareToolkit".into(),
theme: Default::default(), theme: Default::default(),
curr_tab: Default::default(), curr_tab: Default::default(),
tab_pos: iced_aw::tabs::TabBarPosition::Top,
home_page: Default::default(), 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() { 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) .title(MainWindow::title)
.font(iced_fonts::REQUIRED_FONT_BYTES)
.font(ICON_BYTES)
.run(); .run();
} }
#[allow(dead_code)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum MainWindowMsg { pub enum MainWindowMsg {
TabSelected(TabId),
TabClosed(TabId),
ThemeChanged(iced::Theme), ThemeChanged(iced::Theme),
TitleChanged(String), TitleChanged(String),
HomePageMsg(home_page::HomePageMsg), TabSelected(TabId),
HomePage(HomePageMsg),
JlcDownloader(JlcDownloaderMsg),
DbBrowser(DbBrowserMsg),
PartViewer(PartViewerMsg),
Nothing, Nothing,
} }
#[allow(dead_code)]
#[derive(Debug, Default, Clone, PartialEq, Eq)] #[derive(Debug, Default, Clone, PartialEq, Eq)]
enum TabId { pub(crate) enum TabId {
#[default] #[default]
HomePage, HomePage,
JlcDownloader, JlcDownloader,
DbBrowser, DbBrowser,
PartViewer, PartViewer,
} }
#[allow(dead_code)]
struct TabItem {
pub id: TabId,
content: Box<dyn Fn() -> 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 { impl MainWindow {
fn title(&self) -> String { fn title(&self) -> String {
self.title.clone() 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) { fn update(&mut self, msg: MainWindowMsg) {
println!("Process the msg: {msg:?}");
match msg { match msg {
MainWindowMsg::ThemeChanged(theme) => { MainWindowMsg::ThemeChanged(theme) => {
self.theme = theme; self.theme = theme;
@ -76,44 +141,53 @@ impl MainWindow {
println!("Nothing"); println!("Nothing");
iced::debug::time("Test".to_owned()); iced::debug::time("Test".to_owned());
} }
MainWindowMsg::HomePageMsg(message) => { MainWindowMsg::TabSelected(i) => {
self.home_page.update(message); self.curr_tab = i;
} }
MainWindowMsg::TabSelected(tab_id) => { MainWindowMsg::HomePage(msg) => {
self.curr_tab = tab_id; 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> { fn view(&self) -> Element<'_, MainWindowMsg> {
let t = Tabs::new(MainWindowMsg::TabSelected) let h = row![
.tab_icon_position(iced_aw::tabs::Position::Left) self.create_tab_btn(TabId::HomePage),
.on_close(MainWindowMsg::TabClosed) self.create_tab_btn(TabId::JlcDownloader),
.push( self.create_tab_btn(TabId::DbBrowser),
TabId::HomePage, self.create_tab_btn(TabId::PartViewer)
self.home_page.tab_label(), ];
self.home_page.view(), let v = match self.curr_tab {
) TabId::HomePage => self.home_page.view(),
.set_active_tab(&self.curr_tab) TabId::JlcDownloader => self.jlc_downloader.view(),
.icon_font(ICON) TabId::DbBrowser => self.db_browser.view(),
.tab_bar_style(Box::new(iced_aw::style::tab_bar::primary)) TabId::PartViewer => self.part_viewer.view(),
.tab_bar_position(self.tab_pos.clone()); };
w::button("ClickMe").on_press(MainWindowMsg::Nothing).into() // let content = iced::widget::Button::new("Click").on_press(MainWindowMsg::Nothing);
column![h, v].into()
} }
} }
pub trait TabFrame { pub trait TabContent {
type Message; type TabMessage;
fn title(&self) -> String; fn update(&self, msg: Self::TabMessage);
fn tab_label(&self) -> iced_aw::TabLabel; fn view(&self) -> Element<'_, MainWindowMsg> {
fn container(&self) -> Element<'_, Self::Message>; iced::widget::Container::new(self.content())
fn view(&self) -> Element<'_, Self::Message> {
w::Container::new(self.container())
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)
.align_x(Horizontal::Left) .align_x(Horizontal::Left)
.align_y(Vertical::Top) .align_y(Vertical::Top)
.padding(5) .padding(16.0)
.into() .into()
} }
fn content(&self) -> Element<'_, MainWindowMsg>;
} }

View File

@ -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()
}
}

View File

@ -0,0 +1 @@
pub mod tab_header;

View File

@ -0,0 +1,4 @@
#[allow(unused_imports)]
use iced::advanced::renderer;
#[allow(unused_imports)]
use iced::advanced::widget::{self, Widget};