draw some ui
这个ui框架是真tm难用,但是界面也是真的挺好看,省去了后期美化的过程,就当吃屎了吧
This commit is contained in:
parent
117ae5df3c
commit
21353af9e4
22
Cargo.toml
22
Cargo.toml
@ -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",
|
||||||
|
@ -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();
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
pub mod tab_header;
|
4
src/widgets/tab_header.rs
Normal file
4
src/widgets/tab_header.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#[allow(unused_imports)]
|
||||||
|
use iced::advanced::renderer;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use iced::advanced::widget::{self, Widget};
|
Loading…
x
Reference in New Issue
Block a user