/
Sevlagor
/
MGT_Utils
Обзор
Документация
Войти
/
Sevlagor
/
MGT_Utils
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
tmp2
src/view.rs
438 строк
14 KB
Sevlagor
-
08 фев 2026, 21:11
08 фев 2026, 21:11
b63dbc8
Код
Авторство
О чём код?
use std::{ cell::{OnceCell, RefCell, RefMut, }, collections::HashMap, io::{self, Write, }, rc::Rc, }; use core::iter::Iterator; // use windows::Win32::System::Console; use console::{self, Alignment, Color, Key, Style, Term, style}; pub mod components; pub mod id; use crate::{ proc, // data::Data, view::{id::GenID, id::ID, id::ID0}, view::components::*, }; const VIEW_ID: ID = ID0; #[derive(Clone)] pub struct View { name: String, term: Term, max_col: usize, max_row: usize, pos: Pos, residents: Vec<RWork>, registr_by_id: HashMap<ID,RComponent>, // _registr_by_id: HashMap<ID,GuiElement>, registr_by_name: HashMap<String,ID>, _id: OnceCell<ID>, gen_id: OnceCell<GenID>, } impl Owner for View { //TODO fn residents(&self) -> &Vec<RWork> { &self.residents } fn residents_mut(&mut self) -> &mut Vec<RWork> { &mut self.residents } } impl Work for View { fn update(&mut self/* , data: &Data */) { self.residents.iter().for_each(|v| { v.borrow_mut().update(/* data */); }); } fn show(&self) { _ = self.term.hide_cursor(); _ = self.term.clear_screen(); pcap().unwrap(); self.residents.iter().for_each(|v| { v.borrow().show(); }); self.move_cursor_to((2,12).into()); _ = self.term.write_line(&self.name); self.back_cursor_pos(); _ = self.term.show_cursor(); } } impl View { pub fn new(name: &str) -> Option<View> { if let Some(gen_id) = id::new() { let gid = OnceCell::new(); _ = gid.set(gen_id); Some(View { name: name.to_string(), term: Term::stdout(), max_col: 0, max_row: 0, pos: (1,5).into(), residents: vec![], registr_by_id: HashMap::<ID,RComponent>::new(), // _registr_by_id: HashMap::<ID,GuiElement>::new(), registr_by_name: HashMap::<String,ID>::new(), gen_id: gid, _id: { let oc_id = OnceCell::new(); oc_id.get_or_init(|| VIEW_ID); oc_id }, }) } else { None } } pub fn init(&mut self) { self.term.set_title("MAD Games Tycoon 2: Game utilites.".to_string()); let (r, c) = self.term.size(); self.max_col = c as usize; self.max_row = r as usize; // _ = self.term.move_cursor_to(1, self.max_row); // print!("Кампания: {}", data.camp_name()) let _lb_camp = self.create_component::<Label>("lb_camp", VIEW_ID); _lb_camp.borrow_mut().caption = "Кампания: ".to_string(); _lb_camp.borrow_mut().pos = (1, self.max_row).into(); // _ = self.term.move_cursor_to(30, self.max_row); // print!("| Терминал строк: {}, столбцов: {} ", self.max_row, self.max_col); // print!("| Компонентов: {} ", self.registr_by_id.len()); // _ = io::stdout().flush(); // fn func() -> String { // "update-caption".to_string() // } } pub fn create_component<T>(&mut self, name: &str, owner_id: ID) -> Rc<RefCell<T>> where T: Component + 'static + Work { //TODO let cmp = T::new(name, self.clone(), owner_id); let r_cmp = Rc::new(RefCell::new(cmp)); // let t = std::any::type_name<T>(); // match *std::any::type_name<T>() { // "Label" => { GuiElement::Label(cmp) } // _ => { } // } // let gui_el = GuiElement::Label(cmp); self.registration(r_cmp.clone()); if owner_id != VIEW_ID { let owner = self.registr_by_id .get(&owner_id) .unwrap(); owner .borrow_mut() .residents_mut() .push(r_cmp.clone()); } else { self.residents.push(r_cmp.clone()); } r_cmp } //TODO pub fn registration(&mut self, component: RComponent) -> ID { // pub fn registration(&mut self, component: GuiElement) -> ID { let name = component.borrow().name().to_string(); if name == "" { panic!("При регистрации у элемента GUI нет имени"); } let id = self.gen_id.get_mut() .expect("Ошибка при генерации ID") .next(); component.borrow_mut().set_id(id).unwrap(); let x_nm = name.clone(); if let Some(x_id) = self.registr_by_name.insert(name, id) { panic!("Ошибка при регистрации: элемент GUI (ID:{x_id}) с именем '{x_nm}' уже есть"); } if self.registr_by_id.insert(id, component).is_some() { panic!("Ошибка при регистрации элемента GUI по ID"); } id } //TODO pub fn get_component<T>(&self, name: &str) -> Option<&Rc<RefCell<T>>> // Option<T>> // where T: Component + 'static { if let Some(id) = self.registr_by_name.get(name) { let _comp = self.registr_by_id.get(id).unwrap().borrow_mut(); todo!() } None } pub fn input_cmd_loop(&mut self) -> proc::Command { use proc::Command as Cmd; let mut vch: Vec<char> = vec![]; loop { if let Some(key) = self.read_key() { use Key::*; match key { Escape => { return Cmd::Exit; } CtrlC => { return Cmd::Exit; } Char(ch) => { if ch == '1' { return Cmd::NewCamp; } if ch == '2' { let id = self.registr_by_name.get("lb_camp").unwrap(); let _lb = self.registr_by_id.get(id).unwrap(); //TODO неработате т.к. из registr_by_id возвращается dyn Component // а конкретно сдесь нужен Label // _lb.borrow_mut().upd_capt = Some(Box::new( // || { format!("Кампания: {}", data.camp_name()) } // )); self.update(); } if ch == '3' { let id = self.registr_by_name.get("lb_camp").unwrap(); let lb = self.registr_by_id.get(id).unwrap(); let _own_id = lb.borrow_mut().owner_id(); } vch.push(ch); self.move_cursor_to(self.pos); print!("{}", ch); _ = io::stdout().flush(); (self.pos.col < self.max_col-2).then(|| self.pos.col += 1); self.move_cursor_to(self.pos); _ = self.term.move_cursor_to(35, self.max_row-1); print!("| Введено символов: {}", vch.len()); self.move_cursor_to(self.pos); } k if is_arrow_key(&k) => self.move_cursor_for_key(k), Enter => { (self.pos.row < self.max_row-2).then(|| self.pos.row += 1); self.pos.col = 1; self.move_cursor_to(self.pos); } UnknownEscSeq(vch) => { println!("> {} ->", vch.len()); // vch.iter().for_each(|c| print!("{c}")); // println!(); _ = io::stdout().flush(); } _ => { } } } } } pub fn print_at(&self, col: usize, row: usize, text: &str) { _ = self.term.move_cursor_to(col, row); _ = self.term.write_line(text); self.flush(); self.move_cursor_to(self.pos); } pub fn input_str(&self, promt: String) -> String { // let str = self.term.read_line_initial_text(promt).expect("Ошибка в view.input_str"); let mut str = String::new(); _ = self.term.write_line(&promt); self.flush(); loop { if let Some(key) = self.read_key() { use Key::*; match key { Char(ch) => { // print!("{}",ch); let mut s = String::new(); s.push(ch); _ = self.term.write_line(&s); self.flush(); str.push(ch); } Enter => { return str; } _ => {} } } } } fn read_key(&self) -> Option<console::Key> { self.term.read_key_raw().ok() } fn move_cursor_for_key(&mut self, k: Key) { use Key::*; match k { ArrowDown => { (self.pos.row < self.max_row-2).then( || { self.pos.row += 1; self.term.move_cursor_down(1) } ); } ArrowUp => { (self.pos.row >= 2).then( || { self.pos.row -= 1; self.term.move_cursor_up(1) } ); } ArrowRight => { (self.pos.col < self.max_col-2).then( || { self.pos.col += 1; self.term.move_cursor_right(1) } ); } ArrowLeft => { (self.pos.col >= 2).then( || { self.pos.col -= 1; self.term.move_cursor_left(1) } ); } _ => {} } } fn move_cursor_to(&self, pos: Pos) { if pos.col <= self.max_col && pos.row <= self.max_row { _ = self.term.move_cursor_to(pos.col, pos.row) .expect("Ошибка в view.move_cursor_to при перемещении курсора"); } } fn back_cursor_pos(&self) { _ = self.term.move_cursor_to(self.pos.col, self.pos.row) .expect("Ошибка в view.back_cursor_pos при перемещении курсора"); } fn write(&self, text: &str) { _ = self.term.write_str(text); } #[inline] fn flush(&self) { _ = self.term.flush(); } pub fn size(&self) -> Size { let (c,r) = self.term.size(); Size { width: c as usize, height: r as usize } } } #[inline] fn is_arrow_key(k: &Key) -> bool { use Key::*; *k == ArrowDown || *k == ArrowLeft || *k == ArrowRight || *k == ArrowUp } pub fn pcap() -> io::Result<()> { let term = Term::stdout(); term.move_cursor_to(1, 1)?; term.write_line(&style("<<===-- MAD Games Tycoon 2 --===>>").cyan().to_string())?; term.move_cursor_right(1)?; term.write_line(&style("<=- { Game utilites } -=>").cyan().to_string())?; nl(); Ok(()) } #[inline] pub fn nl() { println!(""); } // ################################################################################ #[cfg(test)] mod tests { use super::*; #[test] fn registration() { let mut view = View::new("Test View").expect("View уже создан"); view.init(); let cnt = view.residents.len(); let rview = Rc::new(RefCell::new(view.clone())); let mut lb1 = Label::new("lb1", view.clone(), VIEW_ID); lb1.pos = (1,7).into(); lb1.caption = "Label".to_string(); let mut lb2 = Label::new("lb2", view.clone(), VIEW_ID); lb2.pos = (1,8).into(); lb2.caption = "Label2".to_string(); rview.borrow_mut().registration(Rc::new(RefCell::new(lb1))); rview.borrow_mut().registration(Rc::new(RefCell::new(lb2))); assert_eq!(rview.borrow().registr_by_id.len(), 2+cnt); } #[test] // #[should_panic(expected = "Ошибка при регистрации: элемент GUI (ID:0000:0002) с именем 'lb2' уже есть")] #[should_panic(expected = ") с именем 'lb2' уже есть")] fn fail_registration() { let mut view = View::new("Test View").expect("View уже создан"); view.init(); let rview = Rc::new(RefCell::new(view.clone())); let mut lb1 = Label::new("lb1", view.clone(), VIEW_ID); lb1.pos = (1,7).into(); lb1.caption = "Label".to_string(); let mut lb2 = Label::new("lb2", view.clone(), VIEW_ID); lb2.pos = (1,8).into(); lb2.caption = "Label2".to_string(); let mut lb3 = Label::new("lb2", view.clone(), VIEW_ID); lb3.pos = (1,8).into(); lb3.caption = "Label2".to_string(); rview.borrow_mut().registration(Rc::new(RefCell::new(lb1))); rview.borrow_mut().registration(Rc::new(RefCell::new(lb2))); rview.borrow_mut().registration(Rc::new(RefCell::new(lb3))); } #[test] fn link_with_owner() { let mut _view = View::new("Test View").expect("View уже создан"); _view.init(); let _r_lb = _view.create_component::<Label>("lb", VIEW_ID); _view.name = "Modif_TestView".to_string(); // if let Some(own) = &r_lb.borrow_mut().owner { // if own.strong_count() == 0 { // // Тоже не упградиться // let dt = own.upgrade().expect("не упградиться"); // let ddt = dt.borrow_mut(); // assert_eq!(ddt.name(),"Modif_TestView".to_string()); // } // else { panic!() } // } // else { panic!() }; } }