BreweryControlSystem/code/src/app.rs

935 lines
40 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

use std::{
collections::{HashMap, HashSet},
default::Default,
str::FromStr,
sync::Arc,
};
use crate::{
database::DBOperator,
material_tab::MaterialTabViewer,
misc,
models::{
Equipment, EquipmentModalState, LoginModalState, LoginStatus, Material, MaterialCategory,
MaterialRow, ModalStatus, ModalWinState, Position, Salary, SalaryModalState, Worker,
},
recipe_tab::RecipeTabViewer,
reports::Reporter,
tab::*,
worker_tab::{self, *},
};
use bigdecimal::ToPrimitive;
use chrono::{Datelike, NaiveDate};
use egui::{TextBuffer, Vec2, mutex::RwLock};
use egui_dock::{DockArea, Style, TabViewer};
use egui_extras::{Column, TableBuilder};
use sha2::{Digest, Sha256};
use sqlx::types::BigDecimal;
pub struct App<'a> {
pub login_modal_state: LoginModalState<'a>,
pub tree: egui_dock::DockState<Tab>,
pub main_viewer: MainTabViewer,
pub db_oper: DBOperator,
pub rt: tokio::runtime::Runtime,
pub is_admin: bool,
}
impl Default for App<'_> {
fn default() -> Self {
let mut tree = egui_dock::DockState::new(vec![
Tab {
tab_type: TabTypes::Equipment,
title: "Оборудование".to_owned(),
},
Tab {
tab_type: TabTypes::Material,
title: "Сырьё".to_owned(),
},
Tab {
tab_type: TabTypes::Worker,
title: "Сотрудники".to_owned(),
},
Tab {
tab_type: TabTypes::Salary,
title: "Выплаты".to_owned(),
},
Tab {
tab_type: TabTypes::Recipe,
title: "Рецепты".to_owned(),
},
Tab {
tab_type: TabTypes::Order,
title: "Заказы".to_owned(),
},
Tab {
tab_type: TabTypes::Client,
title: "Клиенты".to_owned(),
},
Tab {
tab_type: TabTypes::Settings,
title: "Настройки".to_owned(),
},
]);
let main_viewer = MainTabViewer::default();
let rt = tokio::runtime::Runtime::new().unwrap();
Self {
tree,
main_viewer,
login_modal_state: LoginModalState {
is_open: true,
data: HashMap::from([("login", String::new()), ("password", String::new())]),
status: crate::models::LoginStatus::Login,
..Default::default()
},
db_oper: rt.block_on(DBOperator::new()),
rt,
is_admin: false,
}
}
}
impl App<'_> {
pub fn new(_cc: &eframe::CreationContext<'_>) -> Self {
Default::default()
}
}
impl eframe::App for App<'_> {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
if self.login_modal_state.status == LoginStatus::Finished {
ui.horizontal(|ui| {
ui.label(self.login_modal_state.data.get("login").unwrap());
if ui.button("Выйти").clicked() {
self.login_modal_state.is_open = true;
self.login_modal_state.status = LoginStatus::Login;
self.login_modal_state.data.insert("login", String::new());
self.login_modal_state
.data
.insert("password", String::new());
}
});
}
if self.login_modal_state.is_open {
egui::Modal::new(egui::Id::new("login_modal")).show(ui.ctx(), |ui| {
ui.label("Пройдите авторизацию:");
ui.add(
egui::TextEdit::singleline(
self.login_modal_state.data.get_mut("login").unwrap(),
)
.hint_text("Введите логин"),
);
ui.add(
egui::TextEdit::singleline(
self.login_modal_state.data.get_mut("password").unwrap(),
)
.password(true)
.hint_text("Пароль"),
);
if self.login_modal_state.fail {
ui.label(&self.login_modal_state.fail_message);
}
ui.vertical_centered(|ui| {
if ui.button("Авторизоваться").clicked()
|| ui.input(|i| i.key_pressed(egui::Key::Enter))
{
let uname = self.login_modal_state.data.get("login").unwrap().clone();
self.login_modal_state.fail = false;
let mut hashed_pass = Sha256::new();
hashed_pass.update(self.login_modal_state.data.get("password").unwrap());
let pass_hash = hex::encode(hashed_pass.finalize());
if self.rt.block_on(async {
self.db_oper
.check_password(uname.clone(), pass_hash)
.await
.unwrap()
}) {
self.login_modal_state.fail = false;
self.login_modal_state.status = crate::models::LoginStatus::Finished;
self.login_modal_state.is_open = false;
if self.rt.block_on(async {
self.db_oper.check_admin(uname.clone()).await.unwrap()
}) {
self.main_viewer.is_admin = true;
} else {
self.main_viewer.is_admin = false;
}
self.main_viewer = MainTabViewer::new(self.main_viewer.is_admin);
} else {
self.login_modal_state.fail = true;
self.login_modal_state.fail_message =
"Неверные логин или пароль".to_string();
}
}
});
});
}
DockArea::new(&mut self.tree)
.style(Style::from_egui(ui.style().as_ref()))
.show_inside(ui, &mut self.main_viewer);
}
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if self.main_viewer.is_dark_theme {
ctx.set_visuals(egui::Visuals::dark());
} else {
ctx.set_visuals(egui::Visuals::light());
}
ctx.set_zoom_factor(self.main_viewer.interface_scale_ratio);
}
}
struct MainTabViewer {
workers: Arc<RwLock<Vec<Worker>>>,
equipment: Arc<RwLock<Vec<Equipment>>>,
salaries: Arc<RwLock<Vec<Salary>>>,
db_oper: DBOperator,
worker_tabs: WorkerTabViewer,
worker_tree: egui_dock::DockState<Tab>,
material_tabs: MaterialTabViewer,
material_tree: egui_dock::DockState<Tab>,
recipe_tab: RecipeTabViewer,
rt: tokio::runtime::Runtime,
equipment_modal_state: EquipmentModalState,
salary_modal_state: SalaryModalState,
is_dark_theme: bool,
interface_scale_ratio: f32,
is_admin: bool,
reporter: Reporter,
}
impl Default for MainTabViewer {
fn default() -> Self {
let rt = tokio::runtime::Runtime::new().unwrap();
let db_oper = rt.block_on(async { DBOperator::new().await });
Self {
workers: Arc::new(RwLock::new(
rt.block_on(async { db_oper.get_workers().await.unwrap() }),
)),
equipment: Arc::new(RwLock::new(
rt.block_on(async { db_oper.get_equipment().await.unwrap() }),
)),
salaries: Arc::new(RwLock::new(
rt.block_on(async { db_oper.get_salaries().await.unwrap() }),
)),
db_oper,
worker_tabs: WorkerTabViewer::default(),
worker_tree: egui_dock::DockState::new(vec![
Tab {
title: "Работники".to_owned(),
tab_type: TabTypes::WorkerList,
},
Tab {
title: "Должности".to_owned(),
tab_type: TabTypes::WorkerPosition,
},
]),
material_tabs: MaterialTabViewer::default(),
material_tree: egui_dock::DockState::new(vec![
Tab {
title: "Сырьё".to_owned(),
tab_type: TabTypes::MaterialList,
},
Tab {
title: "Тип".to_owned(),
tab_type: TabTypes::MaterialTypeList,
},
]),
recipe_tab: RecipeTabViewer::default(),
rt,
is_dark_theme: true,
interface_scale_ratio: 1.2,
equipment_modal_state: EquipmentModalState {
is_open: false,
can_finish: false,
equipment: Equipment::default(),
status: ModalStatus::Add,
},
salary_modal_state: SalaryModalState {
is_open: false,
can_finish: false,
data: HashMap::from([
("id".to_owned(), String::new()),
("worker_id".to_owned(), String::new()),
("salary_size".to_owned(), String::new()),
("comment".to_owned(), String::new()),
]),
status: ModalStatus::Add,
workers: HashSet::new(),
},
is_admin: false,
reporter: Reporter {},
}
}
}
impl MainTabViewer {
fn update_salary(&mut self) {
self.salaries = Arc::new(RwLock::new(
self.rt
.block_on(async { self.db_oper.get_salaries().await.unwrap() }),
));
}
fn update_equipment(&mut self) {
self.equipment = Arc::new(RwLock::new(
self.rt
.block_on(async { self.db_oper.get_equipment().await.unwrap() }),
));
}
fn get_salary(&self) -> Salary {
Salary {
id: self
.salary_modal_state
.data
.get("id")
.unwrap()
.parse::<i32>()
.unwrap(),
worker: self
.workers
.read()
.iter()
.find(|w| {
&w.id.to_string() == self.salary_modal_state.data.get("worker_id").unwrap()
})
.unwrap()
.clone(),
salary_size: BigDecimal::from_str(
self.salary_modal_state.data.get("salary_size").unwrap(),
)
.unwrap(),
salary_date: chrono::NaiveDate::from_str(
self.salary_modal_state.data.get("salary_date").unwrap(),
)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap()
.and_local_timezone(chrono::Local)
.unwrap(),
comment: self.salary_modal_state.data.get("comment").unwrap().clone(),
}
}
fn new(is_admin: bool) -> Self {
Self {
is_admin,
worker_tabs: WorkerTabViewer::new(is_admin),
material_tabs: MaterialTabViewer::new(is_admin),
recipe_tab: RecipeTabViewer::new(is_admin),
..Default::default()
}
}
fn show_equipment(&mut self, ui: &mut egui::Ui) {
if self.is_admin {
ui.horizontal(|ui| {
if ui.button("Добавить").clicked() {
self.equipment_modal_state.is_open = true;
self.equipment_modal_state.status = ModalStatus::Add;
self.equipment_modal_state.equipment = Equipment::default();
}
});
}
let mut table = TableBuilder::new(ui)
.striped(true)
.resizable(false)
.vscroll(false)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
.column(Column::auto())
.column(Column::auto())
.column(Column::auto())
.column(Column::auto())
.column(Column::auto())
.column(Column::auto())
.sense(egui::Sense::click())
.header(30.0, |mut header| {
header.col(|ui| {
ui.heading("Название");
});
header.col(|ui| {
ui.heading("Инв. номер");
});
header.col(|ui| {
ui.heading("Ответственный");
});
header.col(|ui| {
ui.heading("Дата последнего\nтехобслуживания");
});
header.col(|ui| {
ui.heading("Списано");
});
})
.body(|mut body| {
body.ui_mut().style_mut().interaction.selectable_labels = false;
for eq in self.equipment.read().clone().iter() {
body.row(20.0, |mut row| {
row.col(|ui| {
ui.label(&eq.name);
});
row.col(|ui| {
ui.label(&eq.inv_number);
});
row.col(|ui| {
ui.label(&eq.worker.full_name);
});
row.col(|ui| {
ui.label(eq.maintenance_date.date_naive().to_string());
});
row.col(|ui| {
ui.label(if eq.is_written_off { "Да" } else { "Нет" });
});
row.col(|ui| {
if self.is_admin {
if ui.button("Списать").clicked() {
self.equipment_modal_state.is_open = true;
self.equipment_modal_state.status = ModalStatus::Remove;
self.equipment_modal_state.equipment = eq.clone();
}
}
});
if row.response().double_clicked() {
self.equipment_modal_state.is_open = true;
self.equipment_modal_state.status = ModalStatus::Edit;
self.equipment_modal_state.equipment = eq.clone();
}
});
}
});
if self.equipment_modal_state.is_open {
egui::Modal::new(egui::Id::new("process_equipment_modal")).show(ui.ctx(), |ui| {
let mut date_okay = false;
if ui.button("Закрыть").clicked() || ui.input(|i| i.key_pressed(egui::Key::Escape))
{
self.equipment_modal_state.is_open = false;
}
if self.equipment_modal_state.status != ModalStatus::Remove {
egui::Grid::new("process_equipment_grid").show(ui, |ui| {
ui.label("Название");
ui.add_sized(
Vec2::new(200.0, 20.0),
egui::TextEdit::singleline(
&mut self.equipment_modal_state.equipment.name,
)
.hint_text("Название оборудования"),
);
ui.end_row();
ui.label("Инв. номер");
ui.add(
egui::TextEdit::singleline(
&mut self.equipment_modal_state.equipment.inv_number,
)
.hint_text("НН-00"),
);
ui.end_row();
ui.label("Ответственный");
egui::ComboBox::new("process_equipment_combobox", "")
.selected_text(
self.equipment_modal_state
.equipment
.worker
.full_name
.clone(),
)
.show_ui(ui, |ui| {
for wkrk in self.workers.read().clone().iter() {
ui.selectable_value(
&mut self.equipment_modal_state.equipment.worker,
wkrk.clone(),
&wkrk.full_name,
);
}
});
ui.end_row();
ui.label("Дата последнего\nтехобслуживания");
// let mut date = self
// .equipment_modal_state
// .equipment
// .maintenance_date
// .date_naive()
// .to_string();
// let bdate = date.clone();
let ndate = self
.equipment_modal_state
.equipment
.maintenance_date
.date_naive();
let mut date = misc::naivedate_to_jiff(ndate);
ui.add(egui_extras::DatePickerButton::new(&mut date));
if misc::naivedate_to_jiff(
self.equipment_modal_state
.equipment
.maintenance_date
.date_naive(),
) != date
{
self.equipment_modal_state.equipment.maintenance_date =
misc::jiff_to_naivedate(date)
.and_hms_opt(0, 0, 0)
.unwrap()
.and_local_timezone(chrono::Local)
.unwrap();
}
// if date != bdate {
// self.equipment_modal_state.equipment.maintenance_date =
// match NaiveDate::parse_from_str(&date, "%Y-%m-%d") {
// Ok(o) => {date_okay = true;
// o
// .and_hms_opt(0, 0, 0)
// .unwrap()
// .and_local_timezone(chrono::Local)
// .unwrap()},
// Err(e) => {
// date_okay = false;
// NaiveDate::default()
// .and_hms_opt(0, 0, 0)
// .unwrap()
// .and_local_timezone(chrono::Local)
// .unwrap()
// }
// };
// }
});
} else {
ui.label("Вы уверены, что хотите удалить:");
ui.strong(format!(
"{} | {}?",
self.equipment_modal_state.equipment.name,
self.equipment_modal_state.equipment.inv_number
));
}
let btext = match &self.equipment_modal_state.status {
ModalStatus::Add => "Добавить",
ModalStatus::Edit => "Сохранить",
ModalStatus::Remove => "Списать",
};
match &self.equipment_modal_state.status {
ModalStatus::Remove => {
self.equipment_modal_state.can_finish = true;
}
_ => {
self.equipment_modal_state.can_finish =
self.equipment_modal_state.equipment.name.len() > 0 && date_okay
}
}
let resp = ui.add_enabled(
self.equipment_modal_state.can_finish,
egui::Button::new(btext),
);
if resp.clicked() {
match &self.equipment_modal_state.status {
ModalStatus::Add => self.rt.block_on(async {
self.db_oper
.add_equipment(self.equipment_modal_state.equipment.clone())
.await
.unwrap();
}),
ModalStatus::Edit => self.rt.block_on(async {
self.db_oper
.update_equipment(self.equipment_modal_state.equipment.clone())
.await
.unwrap();
}),
ModalStatus::Remove => {
self.rt.block_on(async {
self.db_oper
.write_off_equipment(self.equipment_modal_state.equipment.id)
.await
.unwrap();
});
}
}
self.equipment_modal_state.is_open = false;
self.update_equipment();
}
});
}
}
fn show_worker(&mut self, ui: &mut egui::Ui) {
let id = ui.make_persistent_id("WorkerMenu");
DockArea::new(&mut self.worker_tree)
.style(Style::from_egui(ui.style().as_ref()))
.id(id)
.show_inside(ui, &mut self.worker_tabs);
}
fn show_material(&mut self, ui: &mut egui::Ui) {
let id = ui.make_persistent_id("MaterialMenu");
DockArea::new(&mut self.material_tree)
.id(id)
.show_inside(ui, &mut self.material_tabs);
}
fn show_salary(&mut self, ui: &mut egui::Ui) {
/*
* Чё надо:
* 1. Список платежей.
*/
if self.is_admin && ui.button("Добавить").clicked() {
self.salary_modal_state
.data
.insert("id".to_owned(), String::new());
self.salary_modal_state
.data
.insert("worker_id".to_owned(), String::new());
self.salary_modal_state
.data
.insert("salary_size".to_owned(), String::new());
self.salary_modal_state
.data
.insert("salary_date".to_owned(), String::new());
self.salary_modal_state
.data
.insert("comment".to_owned(), String::new());
self.salary_modal_state.workers.clear();
self.salary_modal_state.is_open = true;
self.salary_modal_state.status = ModalStatus::Add;
}
TableBuilder::new(ui)
.striped(true)
.columns(Column::auto(), 5)
.sense(egui::Sense::click())
.vscroll(false)
.header(30.0, |mut header| {
header.col(|ui| {
ui.heading("Имя сотрудника");
});
header.col(|ui| {
ui.heading("Размер");
});
header.col(|ui| {
ui.heading("Дата");
});
header.col(|ui| {
ui.heading("Примечание");
});
})
.body(|mut body| {
body.ui_mut().style_mut().interaction.selectable_labels = false;
for sal in (self.salaries.read().iter().clone()) {
body.row(25.0, |mut row| {
row.col(|ui| {
ui.label(&sal.worker.full_name);
});
row.col(|ui| {
ui.label(&sal.salary_size.to_string());
});
row.col(|ui| {
ui.label(&sal.salary_date.date_naive().to_string());
});
row.col(|ui| {
let text: String = sal.comment.chars().take(15).collect();
ui.label(text);
});
row.col(|ui| {
if ui.button("Удалить").clicked() {
self.salary_modal_state
.data
.insert("id".to_owned(), sal.id.to_string());
self.salary_modal_state
.data
.insert("worker_id".to_owned(), sal.worker.id.to_string());
self.salary_modal_state
.data
.insert("salary_size".to_owned(), sal.salary_size.to_string());
self.salary_modal_state.data.insert(
"salary_date".to_owned(),
sal.salary_date.date_naive().to_string(),
);
self.salary_modal_state
.data
.insert("comment".to_owned(), sal.comment.clone());
self.salary_modal_state.is_open = true;
self.salary_modal_state.status = ModalStatus::Remove;
}
});
if row.response().double_clicked() {
self.salary_modal_state
.data
.insert("id".to_owned(), sal.id.to_string());
self.salary_modal_state
.data
.insert("worker_id".to_owned(), sal.worker.id.to_string());
self.salary_modal_state
.data
.insert("salary_size".to_owned(), sal.salary_size.to_string());
self.salary_modal_state.data.insert(
"salary_date".to_owned(),
sal.salary_date.date_naive().to_string(),
);
self.salary_modal_state
.data
.insert("comment".to_owned(), sal.comment.clone());
self.salary_modal_state.is_open = true;
self.salary_modal_state.status = ModalStatus::Edit;
}
});
}
});
if self.salary_modal_state.is_open {
egui::Modal::new(egui::Id::new("salary_modal")).show(ui.ctx(), |ui| {
ui.horizontal(|ui| {
if ui.button("Закрыть").clicked()
|| ui.input(|i| i.key_pressed(egui::Key::Escape))
{
self.salary_modal_state.is_open = false;
}
if ui.button("Отчёт").clicked() {
self.reporter.payment_report(self.get_salary().clone());
}
});
if self.salary_modal_state.status != ModalStatus::Remove {
egui::Grid::new("process_salary_grid").show(ui, |ui| {
let size = ui.available_size();
if self.salary_modal_state.status == ModalStatus::Add {
ui.label("Сотрудник(-и):");
egui::ComboBox::new("process_salary_grid_combobox", "")
.selected_text(format!(
"{} выбран(-о)",
self.salary_modal_state.workers.len()
))
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
.show_ui(ui, |ui| {
for wrkr in self.workers.read().clone().iter() {
let mut checked =
self.salary_modal_state.workers.contains(wrkr);
let res = ui.add(egui::Checkbox::new(
&mut checked,
&wrkr.full_name,
));
if res.clicked() {
if checked {
self.salary_modal_state
.workers
.insert(wrkr.clone());
} else {
self.salary_modal_state.workers.remove(wrkr);
}
}
}
});
ui.end_row();
}
ui.label("Размер платежа:");
ui.add_sized(
size,
egui::TextEdit::singleline(
self.salary_modal_state.data.get_mut("salary_size").unwrap(),
),
);
ui.end_row();
ui.label("Дата платежа:");
ui.add_sized(
size,
egui::TextEdit::singleline(
self.salary_modal_state.data.get_mut("salary_date").unwrap(),
)
.hint_text("1970-01-01"),
);
ui.end_row();
ui.label("Примечание:");
ui.add_sized(
size,
egui::TextEdit::multiline(
self.salary_modal_state.data.get_mut("comment").unwrap(),
),
);
ui.end_row();
});
} else {
let wname = self
.workers
.read()
.clone()
.iter()
.find(|w| {
&w.id.to_string()
== self.salary_modal_state.data.get("worker_id").unwrap()
})
.unwrap()
.full_name
.clone();
ui.label("Вы уверены, что хотите удалить запись о выплате:");
ui.label(format!(
"{}: {} | ${}",
self.salary_modal_state.data.get("salary_date").unwrap(),
wname,
self.salary_modal_state.data.get("salary_size").unwrap()
));
}
let btext = match self.salary_modal_state.status {
ModalStatus::Add => "Добавить",
ModalStatus::Edit => "Сохранить",
ModalStatus::Remove => "Удалить",
};
if ui.button(btext).clicked() {
match self.salary_modal_state.status {
ModalStatus::Add => {
self.rt.block_on(async {
for w in self.salary_modal_state.workers.iter() {
self.db_oper
.add_salary(
w.id,
chrono::NaiveDate::from_str(
self.salary_modal_state
.data
.get("salary_date")
.unwrap(),
)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap()
.and_local_timezone(chrono::Local)
.unwrap(),
BigDecimal::from_str(
self.salary_modal_state
.data
.get("salary_size")
.unwrap(),
)
.unwrap(),
Some(
self.salary_modal_state
.data
.get("comment")
.unwrap()
.clone(),
),
)
.await
.ok();
}
});
}
ModalStatus::Edit => {
let sal = Salary {
id: self
.salary_modal_state
.data
.get("id")
.unwrap()
.parse::<i32>()
.unwrap(),
worker: self
.workers
.read()
.iter()
.find(|w| {
&w.id.to_string()
== self
.salary_modal_state
.data
.get("worker_id")
.unwrap()
})
.unwrap()
.clone(),
salary_size: BigDecimal::from_str(
self.salary_modal_state.data.get("salary_size").unwrap(),
)
.unwrap(),
salary_date: chrono::NaiveDate::parse_from_str(
self.salary_modal_state.data.get("salary_date").unwrap(),
"%Y-%m-%d",
)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap()
.and_local_timezone(chrono::Local)
.unwrap(),
comment: self
.salary_modal_state
.data
.get("comment")
.unwrap()
.clone(),
};
self.rt.block_on(async {
self.db_oper.update_salary(sal).await;
});
}
ModalStatus::Remove => self.rt.block_on(async {
self.db_oper
.remove_salary(
self.salary_modal_state
.data
.get("id")
.unwrap()
.parse::<i32>()
.unwrap(),
)
.await;
}),
}
self.salary_modal_state.is_open = false;
self.update_salary();
}
});
}
/*
* 2. Возможность добавить платежи.
* 3. Возможность назначить платежи сразу нескольким сотрудникам.
* 4. Возможность отменить платежи.
*/
}
fn show_settings(&mut self, ui: &mut egui::Ui) {
ui.checkbox(&mut self.is_dark_theme, "Тёмная тема");
ui.add(
egui::Slider::new(&mut self.interface_scale_ratio, 1.0..=2.0)
.text("Масштаб интерфейса"),
);
if ui.button("Сбросить Масштаб интерфейса").clicked() {
self.interface_scale_ratio = 1.2;
}
}
fn show_recipe(&mut self, ui: &mut egui::Ui) {
self.recipe_tab.show_recipe_list(ui);
}
}
impl egui_dock::TabViewer for MainTabViewer {
type Tab = Tab;
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
(&*tab.title).into()
}
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
match &tab.tab_type {
TabTypes::Equipment => {
&self.show_equipment(ui);
}
TabTypes::Worker => {
&self.show_worker(ui);
}
TabTypes::Salary => {
&self.show_salary(ui);
}
TabTypes::Material => {
&self.show_material(ui);
}
TabTypes::Settings => {
&self.show_settings(ui);
}
TabTypes::Recipe => {
&self.show_recipe(ui);
}
_ => {
ui.label("Welcome to Avalonia!");
}
}
}
fn allowed_in_windows(&self, _tab: &mut Self::Tab) -> bool {
TABS_CAN_BE_WINDOWS
}
fn is_closeable(&self, _tab: &Self::Tab) -> bool {
false
}
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
egui::Id::new(&tab.title)
}
}