From 3eaf63ba7962cdc32c86ea471f493668cc00bd26 Mon Sep 17 00:00:00 2001 From: Revertron Date: Sun, 8 Dec 2019 12:32:51 +0100 Subject: [PATCH] Made some pancurses interface, but it will lead to a bunch of problems. Commiting just for the history, will change it to web-view. --- Cargo.toml | 3 +- src/main.rs | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 183 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7e3d9d3..24edee6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,13 +3,14 @@ name = "wyrd_ns" version = "0.1.0" authors = ["Revertron "] edition = "2018" - +#![windows_subsystem = "windows"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rust-crypto = "^0.2" num_cpus = "1.10.1" byteorder = "1.3.2" +pancurses = "0.16" serde = { version = "1.0.102", features = ["derive"] } serde_json = "1.0.42" num-bigint = "0.2" diff --git a/src/main.rs b/src/main.rs index 1463484..185761d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,187 @@ +#![windows_subsystem = "windows"] +extern crate pancurses; +use pancurses::{initscr, endwin, Input, noecho, resize_term, Window, start_color, init_pair, colorpair::ColorPair, COLOR_PAIR}; + use wyrd_ns::{Blockchain, Block, Action, Transaction, Signature, Key}; +const COLOR_TEXT: i16 = 0; +const COLOR_TITLE: i16 = 1; +const COLOR_MENU_NORMAL: i16 = 2; +const COLOR_MENU_FOCUSED: i16 = 3; +const COLOR_STATUS: i16 = 4; + fn main() { println!("Wyrd DNS 0.1.0"); - test_blockchain() + run_interface(); + //test_blockchain() +} + +fn init_colors() { + start_color(); + let background = pancurses::COLOR_BLACK; + let accent = pancurses::COLOR_CYAN; + let text = pancurses::COLOR_WHITE; + + init_pair(COLOR_TEXT, text, background); + init_pair(COLOR_TITLE, background, accent); + init_pair(COLOR_MENU_NORMAL, text, background); + init_pair(COLOR_MENU_FOCUSED, background, accent); + init_pair(COLOR_STATUS, background, accent); +} + +fn draw_title(win: &Window, title: &str) { + win.color_set(COLOR_TITLE); + win.mvprintw(0, win.get_beg_x(), format!("{:width$}", title, width = win.get_max_x() as usize)); +} + +fn draw_status(win: &Window, title: &str) { + win.color_set(COLOR_TITLE); + win.mvprintw(win.get_max_y() - 1, win.get_beg_x(), format!("{:width$}", title, width = win.get_max_x() as usize)); +} + +#[derive(Debug)] +pub struct MenuItem { + id: usize, + caption: String, + hint: String +} + +impl MenuItem { + pub fn simple>(id: usize, caption: S) -> Self { + MenuItem{ id, caption: caption.into(), hint: String::new() } + } + + pub fn full>(id: usize, caption: S, hint: S) -> Self { + MenuItem{ id, caption: caption.into(), hint: hint.into() } + } + + pub fn separator() -> Self { + MenuItem { id: 0, caption: String::new(), hint: String::new() } + } + + pub fn is_separator(&self) -> bool { + self.caption.is_empty() + } + + pub fn get_id(&self) -> usize { + self.id + } + + pub fn get_caption(&self) -> &str { + &self.caption + } + + pub fn get_hint(&self) -> &str { + &self.hint + } +} + +struct Menu { + x: i32, + y: i32, + items: Vec, + position: usize, + max_width: usize, +} + +impl Menu { + fn new(x: i32, y: i32, items: Vec) -> Self { + let mut max = 0; + for item in items.iter() { + if item.get_caption().len() > max { + max = item.get_caption().len(); + } + } + Menu{ x, y, items, position: 0, max_width: max } + } + + fn up(&mut self) { + if self.position > 0 { + self.position = self.position - 1; + if self.items[self.position].is_separator() { + self.up(); + } + } + } + + fn down(&mut self) { + if self.position < (self.items.len() - 1) { + self.position = self.position + 1; + if self.items[self.position].is_separator() { + self.down(); + } + } + } + + fn position(&self) -> usize { + self.position + } + + fn current(&self) -> &MenuItem { + &self.items[self.position] + } + + fn paint(&self, win: &Window) { + let mut pos = 0; + for item in self.items.iter() { + let color = { if pos == self.position {COLOR_MENU_FOCUSED} else {COLOR_MENU_NORMAL} }; + win.color_set(color); + win.mvprintw(self.y + pos as i32, self.x, format!(" {:width$} ", item.get_caption(), width = self.max_width)); + pos = pos + 1; + } + } +} + +fn run_interface() { + let window = initscr(); + resize_term(24, 80); + init_colors(); + draw_title(&window, " Wyrd 0.1.0"); + window.refresh(); + window.keypad(true); + window.timeout(20); + pancurses::noecho(); + window.keypad(true); + pancurses::curs_set(0); + let mut menu = create_menu(); + + loop { + match window.getch() { + Some(Input::Character(c)) => { + if c == '\n' { + println!("Selected {:?}", menu.current()); + } else { + window.addch(c); + } + }, + Some(Input::KeyResize) => { resize_term(0, 0); }, + Some(Input::KeyUp) => { menu.up(); }, + Some(Input::KeyDown) => { menu.down(); }, + Some(Input::KeyEnter) => { println!("Selected {:?}", menu.current()); }, + Some(Input::KeyDC) => break, + Some(input) => { window.addstr(&format!("{:?}", input)); }, + None => () + } + draw_status(&window, menu.current().get_hint()); + menu.paint(&window); + window.refresh(); + } + endwin(); +} + +fn create_menu() -> Menu { + let menu_items = vec![ + MenuItem::full(1, "Key create", "Create keypair to sign domain operations"), + MenuItem::full(2, "Key load", "Load existing keypair"), + MenuItem::separator(), + MenuItem::full(3, "Domain create new", "Create and mine new domain"), + MenuItem::full(4, "Domain change records", "Change DNS records for your domain"), + MenuItem::full(5, "Domain renew", "Renew your domain name, needs additional mining"), + MenuItem::full(6, "Domain transfer", "Transfer your domain to a new owner (new keypair)"), + MenuItem::separator(), + MenuItem::full(7, "Test blockchain", "Do some test blockchain operations with simple mining") + ]; + Menu::new(1, 3, menu_items) } fn test_blockchain() -> () { @@ -11,7 +190,7 @@ fn test_blockchain() -> () { let signature = Signature::from_file("default.key", "").unwrap(); // Creating transaction - let action = Action::new_domain("test.zz".to_owned(), &signature, vec!["AAAA IN 301:2925::1".to_owned()], vec![], 365); + let action = Action::new_domain("test.zz".to_owned(), &signature, vec!["AAAA IN 301:2925::1".to_owned()], vec!["testing".to_owned(), "example".to_owned()], 365); let mut transaction = Transaction::new(action, signature.get_public().clone()); // Signing it with private key from Signature