use crate::prelude::*;
#[derive(Debug, PartialEq, Default)]
enum AboutTab {
#[default]
Details,
Legal,
}
#[derive(Debug)]
pub struct AboutDialog {
open: bool,
tab: AboutTab,
name: String,
icon_uri: Option<String>,
version: Option<String>,
developer: Option<String>,
website_url: Option<String>,
issues_url: Option<String>,
description: Option<String>,
description_long: Option<String>,
license_year: Option<u32>,
license_name: Option<String>,
license_text: Option<String>,
}
impl AboutDialog {
pub fn new(name: impl Into<String>) -> Self {
Self {
open: false,
tab: AboutTab::default(),
name: name.into(),
icon_uri: None,
version: None,
developer: None,
website_url: None,
issues_url: None,
description: None,
description_long: None,
license_year: None,
license_name: None,
license_text: None,
}
}
pub fn icon_uri(mut self, icon_uri: impl Into<String>) -> Self {
self.icon_uri = Some(icon_uri.into());
self
}
pub fn version(mut self, version: impl Into<String>) -> Self {
self.version = Some(version.into());
self
}
pub fn developer(mut self, developer: impl Into<String>) -> Self {
self.developer = Some(developer.into());
self
}
pub fn website_url(mut self, website_url: impl Into<String>) -> Self {
self.website_url = Some(website_url.into());
self
}
pub fn issues_url(mut self, issues_url: impl Into<String>) -> Self {
self.issues_url = Some(issues_url.into());
self
}
pub fn description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
pub fn description_long(mut self, description_long: impl Into<String>) -> Self {
self.description_long = Some(description_long.into());
self
}
pub fn license_year(mut self, license_year: u32) -> Self {
self.license_year = Some(license_year);
self
}
pub fn license_name(mut self, license_name: impl Into<String>) -> Self {
self.license_name = Some(license_name.into());
self
}
pub fn license_text(mut self, license_text: impl Into<String>) -> Self {
self.license_text = Some(license_text.into());
self
}
pub fn open(&mut self) {
self.open = true;
}
fn has_details(&self) -> bool {
self.developer.is_some() || self.website_url.is_some() || self.issues_url.is_some() || self.description_long.is_some()
}
fn has_legal(&self) -> bool {
self.license_year.is_some() || self.license_name.is_some() || self.license_text.is_some()
}
fn details(&self, ui: &mut egui::Ui) {
if let Some(developer) = &self.developer {
ui.label(format!("Developed by {developer}"));
}
if self.developer.is_some() && (self.website_url.is_some() || self.issues_url.is_some()) {
ui.add_space(6.0);
}
if let Some(website_url) = &self.website_url {
ui.hyperlink_to("Website", website_url);
}
if let Some(issues_url) = &self.issues_url {
ui.hyperlink_to("Report an issue", issues_url);
}
if let Some(description_long) = &self.description_long {
if self.developer.is_some() || self.website_url.is_some() || self.issues_url.is_some() {
ui.add_space(10.0);
}
ui.label(RichText::new(description_long).size(11.5).weak());
}
}
fn legal(&self, ui: &mut egui::Ui) {
if let Some(license_name) = &self.license_name {
ui.label(RichText::new(license_name).strong());
}
if let Some(license_year) = self.license_year {
if self.license_name.is_some() {
ui.add_space(4.0);
}
let copyright = match &self.developer {
Some(developer) => format!("© {license_year} {developer}"),
None => format!("© {license_year}"),
};
ui.label(copyright);
}
if let Some(license_text) = &self.license_text {
if self.license_name.is_some() || self.license_year.is_some() {
ui.add_space(10.0);
}
ui.add(Label::new(RichText::new(license_text).text_style(TextStyle::Small)).wrap_mode(TextWrapMode::Wrap));
}
}
}
impl LeafWidget for AboutDialog {
fn render(&mut self, ui: &mut egui::Ui, _frame: &mut Frame) {
if !self.open {
return;
}
Modal::new(egui::Id::new("about_dialog")).show(ui, |ui| {
ui.set_width(420.0);
ui.set_max_height(560.0);
ui.vertical_centered(|ui| {
ui.add_space(12.0);
if let Some(icon_uri) = &self.icon_uri {
ui.add(
Image::from_uri(icon_uri)
.fit_to_exact_size(egui::vec2(64.0, 64.0))
.maintain_aspect_ratio(true),
);
ui.add_space(8.0);
}
ui.label(RichText::new(&self.name).size(20.0).strong());
if let Some(description) = &self.description {
ui.label(RichText::new(description).size(13.0).weak());
}
if let Some(version) = &self.version {
if self.description.is_some() {
ui.add_space(2.0);
}
ui.label(
RichText::new(format!("Version {version}"))
.size(12.0)
.weak(),
);
}
ui.add_space(12.0);
});
let has_details = self.has_details();
let has_legal = self.has_legal();
if has_details || has_legal {
ui.separator();
if has_details && has_legal {
ui.horizontal(|ui| {
ui.selectable_value(&mut self.tab, AboutTab::Details, "Details");
ui.selectable_value(&mut self.tab, AboutTab::Legal, "Legal");
});
ui.separator();
}
ui.add_space(6.0);
ScrollArea::vertical().max_height(300.0).show(ui, |ui| {
if has_details && (!has_legal || self.tab == AboutTab::Details) {
self.details(ui);
} else {
self.legal(ui);
}
});
ui.add_space(8.0);
}
ui.separator();
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
if ui.button("Close").clicked() {
self.open = false;
}
});
});
}
}