Rework project display

This commit is contained in:
Piotr Siuszko 2023-03-07 19:49:45 +01:00
parent dba911d2ae
commit 80923b610b
2 changed files with 137 additions and 178 deletions

View File

@ -4,4 +4,4 @@ pub const APP_NAME: &str = "Rusty Unity Hub";
pub const VERTICAL_SPACING: f32 = 8.0; pub const VERTICAL_SPACING: f32 = 8.0;
pub const TOP_BUTTON_WIDTH: f32 = 150.0; pub const TOP_BUTTON_WIDTH: f32 = 150.0;
pub const TOP_SIDE_MARGIN: f32 = 10.0; pub const TOP_SIDE_MARGIN: f32 = 10.0;
pub const HEADER_HEIGHT: f32 = 45.0;

View File

@ -1,16 +1,18 @@
use crate::{ use crate::{
consts::HOMEPAGE, consts::HOMEPAGE,
consts::{APP_NAME, TOP_BUTTON_WIDTH, VERSION, VERTICAL_SPACING, TOP_SIDE_MARGIN}, consts::{
APP_NAME, HEADER_HEIGHT, TOP_BUTTON_WIDTH, TOP_SIDE_MARGIN, VERSION, VERTICAL_SPACING,
},
window_tab::WindowTab, window_tab::WindowTab,
}; };
use eframe::{ use eframe::{
egui::{self, Layout, Ui}, egui::{self, Layout, Ui},
epaint::{Color32, FontId, FontFamily}, epaint::{text, Color32, FontFamily, FontId},
}; };
use egui_extras::{Column, TableBuilder}; use egui_extras::{Column, TableBuilder};
use inline_tweak::*;
use rfd::FileDialog; use rfd::FileDialog;
use unity_hub_lib::{consts::FILE_MANAGER, hub::Hub}; use unity_hub_lib::{consts::FILE_MANAGER, hub::Hub};
use inline_tweak::*;
pub struct HubClient { pub struct HubClient {
hub: Hub, hub: Hub,
@ -101,13 +103,18 @@ impl HubClient {
let paths = self.hub.config.unity_search_paths.clone(); let paths = self.hub.config.unity_search_paths.clone();
for (i, path) in paths.iter().enumerate() { for (i, path) in paths.iter().enumerate() {
ui.horizontal( ui.horizontal(|ui| {
|ui| {
ui.label(path); ui.label(path);
let height = tweak!(30.0); let height = tweak!(30.0);
let button_width = tweak!(100.0); let button_width = tweak!(100.0);
ui.allocate_space(egui::vec2(ui.available_width()-button_width-TOP_SIDE_MARGIN,height)); ui.allocate_space(egui::vec2(
if ui.add_sized([button_width, height], egui::Button::new("🚮 Remove")).clicked() { ui.available_width() - button_width - TOP_SIDE_MARGIN,
height,
));
if ui
.add_sized([button_width, height], egui::Button::new("🚮 Remove"))
.clicked()
{
self.hub.config.unity_search_paths.remove(i); self.hub.config.unity_search_paths.remove(i);
self.save_config(true); self.save_config(true);
return; return;
@ -173,88 +180,26 @@ impl HubClient {
}); });
} }
fn draw_project(&mut self, _ctx: &egui::Context, ui: &mut Ui) { fn draw_project(&mut self, _ctx: &egui::Context, ui: &mut Ui) {
let text_height = egui::TextStyle::Body.resolve(ui.style()).size * 2.0; let text_height = egui::TextStyle::Body.resolve(ui.style()).size * tweak!(3.0);
let table = TableBuilder::new(ui) let projects = self.hub.projects.clone();
.striped(true) for (i, project) in projects.iter().enumerate() {
.cell_layout(egui::Layout::left_to_right(egui::Align::Center)) let editor_for_project_exists = self.hub.editor_for_project(project).is_some();
.column(Column::initial(150.0).at_least(150.0)) ui.horizontal(|ui| {
.column(Column::initial(90.0).at_least(40.0)) let color = if i % 2 == 0 {
.column(Column::initial(90.0).at_least(90.0)) Color32::from_rgba_premultiplied(0, 0, 0, 30)
.column(Column::remainder().at_least(260.0)) } else {
.resizable(false); egui::Color32::TRANSPARENT
};
table egui::Frame::none().fill(color).show(ui, |ui| {
.header(25.0, |mut header| { ui.add_sized(
header.col(|ui| { [text_height, text_height],
ui.heading("Name"); egui::Button::new("").frame(false),
ui.add_space(VERTICAL_SPACING);
});
header.col(|ui| {
ui.vertical_centered_justified(|ui| {
ui.heading("Version");
ui.add_space(VERTICAL_SPACING);
});
});
header.col(|ui| {
ui.vertical_centered_justified(|ui| {
ui.heading("Branch");
ui.add_space(VERTICAL_SPACING);
});
});
header.col(|ui| {
ui.with_layout(
Layout::top_down_justified(eframe::emath::Align::Max),
|ui| {
ui.heading("Directory");
ui.add_space(VERTICAL_SPACING);
},
);
});
})
.body(|body| {
body.rows(
text_height,
self.hub.projects.len(),
|row_index, mut row| {
let project = &self.hub.projects[row_index];
let editor_for_project_exists =
self.hub.editor_for_project(project).is_some();
row.col(|ui| {
ui.vertical_centered_justified(|ui| {
ui.add_space(VERTICAL_SPACING - 2.0);
if ui
.add_enabled(
editor_for_project_exists,
egui::Button::new(format!("{}", &project.title)),
) )
.on_disabled_hover_text(format!( .context_menu(|ui| {
"Select different Unity version" ui.menu_button("Open in", |ui| {
))
.clicked()
{
self.hub.run_project_nr(row_index);
}
ui.add_space(VERTICAL_SPACING);
});
});
row.col(|ui| {
ui.with_layout(
Layout::top_down_justified(eframe::emath::Align::Center),
|ui| {
ui.add_space(VERTICAL_SPACING);
let mut text = egui::RichText::new(&project.version);
if !editor_for_project_exists {
text = text.color(Color32::RED);
}
let version_response =
ui.add(egui::Label::new(text).sense(egui::Sense::click()));
version_response.context_menu(|ui| {
for editor in &self.hub.config.editors_configurations { for editor in &self.hub.config.editors_configurations {
let mut text = egui::RichText::new(format!( let mut text = egui::RichText::new(format!("{}", &editor.version));
"Open in {}",
&editor.version
));
if editor.version.contains(&project.version) { if editor.version.contains(&project.version) {
text = text.strong().color(Color32::GREEN); text = text.strong().color(Color32::GREEN);
} }
@ -264,45 +209,12 @@ impl HubClient {
} }
} }
}); });
},
);
});
row.col(|ui| {
ui.with_layout(
Layout::top_down_justified(eframe::emath::Align::Max),
|ui| {
if project.branch.len() < 1 {
return;
}
ui.add_space(VERTICAL_SPACING);
const MAX_BRANCH_LEN: usize = 15;
let is_long = project.branch.len() > MAX_BRANCH_LEN;
let short = if !is_long {
project.branch.clone()
} else {
let mut result =
String::from(&project.branch[0..MAX_BRANCH_LEN]);
result.push_str("...");
result
};
let label = ui.label(egui::RichText::new(short).small()); if ui
if is_long { .button("Open directory")
label.on_hover_text(format!("{}", &project.branch)); .on_hover_text(&project.path)
} .clicked()
}, {
);
});
row.col(|ui| {
ui.with_layout(
Layout::top_down_justified(eframe::emath::Align::Max),
|ui| {
ui.add_space(VERTICAL_SPACING);
let path_response = ui.add(
egui::Label::new(&project.path).sense(egui::Sense::click()),
);
path_response.context_menu(|ui| {
if ui.button("🗁 Open directory").clicked() {
use std::process::Command; use std::process::Command;
Command::new(FILE_MANAGER) Command::new(FILE_MANAGER)
.arg(&project.path) .arg(&project.path)
@ -311,16 +223,53 @@ impl HubClient {
ui.close_menu(); ui.close_menu();
} }
}); });
}, ui.label(egui::RichText::new(format!("{}", &project.title)).heading());
);
if project.branch.len() > 0 {
ui.add_space(TOP_SIDE_MARGIN);
const MAX_BRANCH_LEN: usize = 15;
let is_long = project.branch.len() > MAX_BRANCH_LEN;
let short = if !is_long {
project.branch.clone()
} else {
let mut result = String::from(&project.branch[0..MAX_BRANCH_LEN]);
result.push_str("...");
result
};
let label = ui.label(egui::RichText::new(short).small().weak());
if is_long {
label.on_hover_text(format!("{}", &project.branch));
}
}
let btn_width = tweak!(100.0);
ui.allocate_space(egui::vec2(
ui.available_width() - btn_width - TOP_SIDE_MARGIN,
text_height,
));
let text = if editor_for_project_exists {
egui::RichText::new(format!("{}", "Open"))
} else {
egui::RichText::new(format!("{}", "Open")).weak()
};
let button = egui::Button::new(text);
let added_button = ui.add_sized([btn_width, text_height], button);
if added_button.clicked() {
if editor_for_project_exists {
self.hub.run_project_nr(i);
}
}
}); });
},
);
}); });
} }
}
fn draw_editors_header(&mut self, _ctx: &egui::Context, ui: &mut Ui) { fn draw_editors_header(&mut self, _ctx: &egui::Context, ui: &mut Ui) {
add_header(ui); add_header(ui);
let available_width =
ui.available_width() - TOP_BUTTON_WIDTH - TOP_SIDE_MARGIN - TOP_SIDE_MARGIN;
ui.allocate_space(egui::vec2(available_width, HEADER_HEIGHT));
if ui if ui
.add_sized( .add_sized(
[TOP_BUTTON_WIDTH, 30.0], [TOP_BUTTON_WIDTH, 30.0],
@ -343,6 +292,12 @@ impl HubClient {
fn draw_project_header(&mut self, _ctx: &egui::Context, ui: &mut Ui) { fn draw_project_header(&mut self, _ctx: &egui::Context, ui: &mut Ui) {
add_header(ui); add_header(ui);
let available_width = ui.available_width()
- TOP_BUTTON_WIDTH
- TOP_SIDE_MARGIN
- TOP_SIDE_MARGIN;
ui.allocate_space(egui::vec2(available_width, HEADER_HEIGHT));
if ui if ui
.add_sized( .add_sized(
[TOP_BUTTON_WIDTH, 30.0], [TOP_BUTTON_WIDTH, 30.0],
@ -380,37 +335,40 @@ impl HubClient {
let font_size = tweak!(16.0); let font_size = tweak!(16.0);
let button_size = egui::vec2(ui.available_width(), button_size); let button_size = egui::vec2(ui.available_width(), button_size);
let rich_text = if &self.current_tab == tab { egui::RichText::new(text).strong() } else { egui::RichText::new(text).weak() }.font(FontId::new(font_size, FontFamily::Proportional)); let rich_text = if &self.current_tab == tab {
egui::RichText::new(text).strong()
} else {
egui::RichText::new(text).weak()
}
.font(FontId::new(font_size, FontFamily::Proportional));
ui.add_sized(button_size, egui::Label::new(rich_text).wrap(false).sense(egui::Sense::click())) ui.add_sized(
button_size,
egui::Label::new(rich_text)
.wrap(false)
.sense(egui::Sense::click()),
)
.clicked() .clicked()
} }
fn draw_side_panel(&mut self, ui: &mut Ui) { fn draw_side_panel(&mut self, ui: &mut Ui) {
ui.with_layout( ui.with_layout(Layout::top_down(eframe::emath::Align::Min), |ui| {
Layout::top_down(eframe::emath::Align::Min), if self.tab_button(ui, &WindowTab::Projects, tweak!("📦 Projects")) {
|ui| {
if self.tab_button(ui, &WindowTab::Projects, tweak!("📦 Projects"))
{
self.current_tab = WindowTab::Projects; self.current_tab = WindowTab::Projects;
} }
if self.tab_button(ui, &WindowTab::Editors, tweak!("🛠 Editors")) if self.tab_button(ui, &WindowTab::Editors, tweak!("🛠 Editors")) {
{
self.current_tab = WindowTab::Editors; self.current_tab = WindowTab::Editors;
} }
}, });
);
} }
} }
fn add_header(ui: &mut Ui) { fn add_header(ui: &mut Ui) {
let header_height = tweak!(45.0); let text = egui::RichText::new(APP_NAME)
let text = .font(FontId::new(26.0, FontFamily::Name("semibold".into())))
egui::RichText::new(APP_NAME).font(FontId::new(26.0, FontFamily::Name("semibold".into()))).strong(); .strong();
ui.allocate_space(egui::vec2(TOP_SIDE_MARGIN, header_height)); ui.allocate_space(egui::vec2(TOP_SIDE_MARGIN, HEADER_HEIGHT));
ui.add(egui::Label::new(text)); ui.add(egui::Label::new(text));
let available_width = ui.available_width() - TOP_BUTTON_WIDTH - TOP_SIDE_MARGIN - TOP_SIDE_MARGIN;
ui.allocate_space(egui::vec2(available_width, header_height));
} }
impl eframe::App for HubClient { impl eframe::App for HubClient {
@ -419,7 +377,8 @@ impl eframe::App for HubClient {
.frame(egui::Frame::canvas(&ctx.style())) .frame(egui::Frame::canvas(&ctx.style()))
.show(ctx, |ui| { .show(ctx, |ui| {
ui.with_layout( ui.with_layout(
egui::Layout::left_to_right(egui::Align::Center).with_cross_align(eframe::emath::Align::Center), egui::Layout::left_to_right(egui::Align::Center)
.with_cross_align(eframe::emath::Align::Center),
|ui| { |ui| {
match self.current_tab { match self.current_tab {
WindowTab::Projects => self.draw_project_header(&ctx, ui), WindowTab::Projects => self.draw_project_header(&ctx, ui),