229 lines
7.4 KiB
Rust
Executable file
229 lines
7.4 KiB
Rust
Executable file
use std::{fmt::Display, string::ToString, sync::Arc};
|
|
|
|
use arch::{Arch, ArchList};
|
|
use choice::ChoiceOption;
|
|
use egui::{Galley, Rect, Ui};
|
|
use versions::ChoiceHolder;
|
|
|
|
pub(crate) mod arch;
|
|
#[macro_use]
|
|
pub(crate) mod choice;
|
|
mod versions;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct App {
|
|
env_setup_level: EnvSetupLevel,
|
|
preview_channel: bool,
|
|
msvc: ChoiceHolder<String, Vec<String>>,
|
|
sdk: ChoiceHolder<String, Vec<String>>,
|
|
host_arch: ChoiceHolder<Arch, ArchList>,
|
|
target_arch: ChoiceHolder<Arch, ArchList>,
|
|
install_path: String,
|
|
}
|
|
|
|
impl Default for App {
|
|
fn default() -> Self {
|
|
Self {
|
|
env_setup_level: EnvSetupLevel::default(),
|
|
preview_channel: false,
|
|
msvc: ChoiceHolder::new(ChoiceOption::MsvcVersion(choices!("2019", "2022"))).unwrap(),
|
|
sdk: ChoiceHolder::new(ChoiceOption::SdkVersion(choices!("10.0.22621.0"))).unwrap(),
|
|
host_arch: ChoiceHolder::new(ChoiceOption::HostArch(ArchList::default())).unwrap(),
|
|
target_arch: ChoiceHolder::new(ChoiceOption::TargetArch(ArchList::default())).unwrap(),
|
|
install_path: String::new(),
|
|
}
|
|
}
|
|
}
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq)]
|
|
pub enum EnvSetupLevel {
|
|
#[default]
|
|
None,
|
|
User,
|
|
Global,
|
|
}
|
|
|
|
impl EnvSetupLevel {
|
|
pub const ALL: [Self; 3] = [Self::None, Self::User, Self::Global];
|
|
}
|
|
|
|
impl Display for EnvSetupLevel {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let option_strs = match self {
|
|
&Self::None => "Create environment setup scripts",
|
|
&Self::User => "Add to user environment",
|
|
&Self::Global => "Add to global environment",
|
|
};
|
|
|
|
f.write_str(option_strs)
|
|
}
|
|
}
|
|
|
|
impl App {
|
|
fn env_setup_selection(&mut self, ui: &mut Ui) {
|
|
egui::ComboBox::from_label(String::new())
|
|
.width(ui.available_width() / 1.5)
|
|
.selected_text(self.env_setup_level.to_string())
|
|
.show_ui(ui, |ui| {
|
|
EnvSetupLevel::ALL.iter().for_each(|opt| {
|
|
ui.selectable_value(&mut self.env_setup_level, *opt, format!("{}", opt));
|
|
});
|
|
});
|
|
}
|
|
|
|
fn selection_menu<T: ToString + From<String> + PartialEq, V: Into<Vec<String>>>(
|
|
selected: &mut T,
|
|
ui: &mut Ui,
|
|
width: f32,
|
|
component: ChoiceOption<V>,
|
|
) {
|
|
let name = component.to_string();
|
|
|
|
ui.label(name);
|
|
egui::ComboBox::from_id_salt(&component)
|
|
.width(width)
|
|
.selected_text(selected.to_string()) // FIXME
|
|
.show_ui(ui, |ui| {
|
|
component.options().iter().for_each(|opt| {
|
|
ui.selectable_value(selected.into(), opt.clone().into(), opt.to_string());
|
|
});
|
|
});
|
|
}
|
|
|
|
fn boxed_inner(
|
|
ui: &mut Ui,
|
|
text: String,
|
|
box_rect: Rect,
|
|
text_rect: Rect,
|
|
galley: Arc<Galley>,
|
|
) {
|
|
let left = box_rect.left();
|
|
let right = box_rect.right();
|
|
let top = box_rect.top();
|
|
let bottom = box_rect.bottom();
|
|
let stroke = ui.style().visuals.window_stroke();
|
|
|
|
// Left side
|
|
ui.painter()
|
|
.line_segment([egui::pos2(left, top), egui::pos2(left, bottom)], stroke);
|
|
|
|
// Bottom side
|
|
ui.painter().line_segment(
|
|
[egui::pos2(left, bottom), egui::pos2(right, bottom)],
|
|
stroke,
|
|
);
|
|
|
|
// Right side
|
|
ui.painter()
|
|
.line_segment([egui::pos2(right, top), egui::pos2(right, bottom)], stroke);
|
|
|
|
// Top side
|
|
ui.painter().line_segment(
|
|
[egui::pos2(left, top), egui::pos2(text_rect.left(), top)],
|
|
stroke,
|
|
);
|
|
ui.painter().line_segment(
|
|
[
|
|
egui::pos2(text_rect.left() + galley.size().x, top),
|
|
egui::pos2(right, top),
|
|
],
|
|
stroke,
|
|
);
|
|
|
|
ui.painter().text(
|
|
text_rect.left_center(),
|
|
egui::Align2::LEFT_CENTER,
|
|
text,
|
|
ui.style().text_styles[&egui::TextStyle::Body].clone(),
|
|
ui.style().visuals.text_color(),
|
|
);
|
|
}
|
|
|
|
pub fn boxed<R>(ui: &mut Ui, heading: impl ToString, draw: impl FnOnce(&mut Ui) -> R) {
|
|
ui.vertical(|ui| {
|
|
let text = heading.to_string();
|
|
let margin = ui.spacing().window_margin;
|
|
let available_width = ui.available_width() - margin.left as f32 - margin.right as f32;
|
|
|
|
ui.horizontal(|ui| {
|
|
ui.add_space(margin.left as f32);
|
|
ui.vertical(|ui| {
|
|
ui.set_width(available_width);
|
|
|
|
egui::Frame::new()
|
|
.inner_margin(epaint::Margin::symmetric(10, 15))
|
|
.show(ui, draw);
|
|
|
|
let galley = ui.painter().layout_no_wrap(
|
|
text.clone(),
|
|
ui.style().text_styles[&egui::TextStyle::Body].clone(),
|
|
egui::Color32::LIGHT_GRAY, // TOOD: use something within defaults
|
|
);
|
|
|
|
let border_rect = ui.min_rect();
|
|
let text_rect = egui::Rect::from_min_size(
|
|
egui::pos2(
|
|
border_rect.left() + 8.0,
|
|
border_rect.top() - galley.size().y / 2.0,
|
|
),
|
|
egui::vec2(galley.size().x, galley.size().y),
|
|
);
|
|
|
|
Self::boxed_inner(ui, text, border_rect, text_rect, galley);
|
|
ui.add_space(margin.right as f32);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
impl eframe::App for App {
|
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
|
egui::CentralPanel::default().show(ctx, |ui| {
|
|
ui.horizontal(|ui| {
|
|
self.env_setup_selection(ui);
|
|
ui.checkbox(&mut self.preview_channel, "Preview channel");
|
|
});
|
|
|
|
ui.add_space(15.0);
|
|
ui.horizontal(|ui| {
|
|
let width_per_choice = ctx.screen_rect().width() / 4.75;
|
|
macro_rules! selection_menus {
|
|
($($choice:expr),*) => {
|
|
$(ui.vertical(|ui| {
|
|
let x = $choice.available.clone();
|
|
Self::selection_menu($choice.selected_mut(), ui, width_per_choice, x)
|
|
});)*
|
|
};
|
|
}
|
|
|
|
selection_menus![
|
|
self.msvc,
|
|
self.sdk,
|
|
self.host_arch,
|
|
self.target_arch
|
|
];
|
|
});
|
|
|
|
ui.add_space(25.0);
|
|
Self::boxed(ui, "Destination Folder", |ui| {
|
|
ui.horizontal(|ui| {
|
|
ui.horizontal_centered(|ui| {
|
|
let path_selection_box = egui::TextEdit::singleline(&mut self.install_path)
|
|
.hint_text("Select folder path");
|
|
ui.add(path_selection_box);
|
|
|
|
ui.button("Browse...")
|
|
});
|
|
});
|
|
});
|
|
|
|
ui.horizontal(|ui| {
|
|
ui.checkbox(&mut true, "I accept the License Agreement");
|
|
ui.add_space(ui.available_width() - 45.0);
|
|
if ui.button("Install").clicked() {
|
|
// pop out into console
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|