mod error_window;
mod exit_window;
mod info_window;
mod input;
mod ll;
mod main_window;
mod result;
mod statusbar;
mod titlebar;
mod traits;
mod utils;
use std::char::from_u32;
use std::process::exit;
use kconfig_represent::{ConfigRegistry, Error, LoadError};
use ncurses::*;
use self::result::HandleResult;
use self::traits::WindowLike;
pub fn ui_loop(registry: ConfigRegistry, load_error: &Option<LoadError>) {
utils::initialize();
wcolor_set(stdscr(), utils::ColorPair::Default.raw());
if let Some(error) = load_error {
display_load_error(error);
}
let mut statusbar = statusbar::Statusbar::new();
let mut titlebar = titlebar::Titlebar::new();
let mut main_window = main_window::MainWindow::new();
let mut exit_window: Option<exit_window::ExitWindow> = None;
let mut info_window: Option<info_window::InfoWindow> = None;
main_window.set_registry(registry);
let mut update = true;
let mut force_recreate = false;
let mut screen_height = 0;
let mut screen_width = 0;
loop {
let new_screen_height = getmaxy(stdscr());
let new_screen_width = getmaxx(stdscr());
if screen_height != new_screen_height || screen_width != new_screen_width || force_recreate
{
screen_height = new_screen_height;
screen_width = new_screen_width;
utils::recreate_window(&mut statusbar);
utils::recreate_window(&mut titlebar);
utils::recreate_window(&mut main_window);
if let Some(w) = exit_window.as_mut() {
utils::recreate_window(w);
}
if let Some(w) = info_window.as_mut() {
utils::recreate_window(w);
}
refresh();
update = true;
force_recreate = false;
}
if update {
statusbar.draw();
titlebar.draw();
main_window.draw();
if let Some(w) = exit_window.as_mut() {
w.draw();
}
if let Some(w) = info_window.as_mut() {
w.draw();
}
update = false;
}
if let None = exit_window {
if let None = info_window {
match main_window.handle_ch(get_wch()) {
HandleResult::Exit => {
let is_popped = match main_window.pop_selection() {
Ok(is_popped) => is_popped,
Err(e) => exit_unsuccessful(e),
};
if !is_popped && { main_window.changed() } {
exit_window = Some(exit_window::ExitWindow::new());
force_recreate = true;
} else if !is_popped {
break;
} else {
force_recreate = true;
}
}
HandleResult::NavDown => main_window.increment_menu_index(),
HandleResult::NavUp => main_window.decrement_menu_index(),
HandleResult::Select => {
if let Err(e) = main_window.activate_selection() {
exit_unsuccessful(e)
} else {
force_recreate = true;
}
}
HandleResult::Info => {
let result = main_window.active_descriptor_info();
match result {
Ok(info) => {
if !info.is_empty() {
let mut window = info_window::InfoWindow::new();
window.descriptor_info(info);
info_window = Some(window);
force_recreate = true;
}
}
Err(e) => exit_unsuccessful(e),
}
}
HandleResult::None => (),
HandleResult::Char(c) => main_window.addchar(c),
HandleResult::Backspace => main_window.rmchar_left(),
HandleResult::Delete => main_window.rmchar_right(),
HandleResult::MoveLeft => main_window.char_left(),
HandleResult::MoveRight => main_window.char_right(),
}
} else {
match main_window.handle_ch(get_wch()) {
HandleResult::Select | HandleResult::Exit | HandleResult::Backspace => {
if let Some(w) = info_window.as_mut() {
w.del();
info_window = None;
force_recreate = true;
}
}
_ => (),
}
}
} else {
match from_u32(getch() as u32) {
Some('S') | Some('s') => {
if let Err(e) = main_window.save() {
exit_unsuccessful(e)
}
break;
}
Some('C') | Some('c') => {
if let Some(w) = exit_window.as_mut() {
w.del();
exit_window = None;
force_recreate = true;
}
}
Some('X') | Some('x') => {
break;
}
_ => (),
}
}
}
exit_regular();
}
fn display_load_error(error: &LoadError) {
let mut error_window = error_window::ErrorWindow::new();
error_window.load_error(error);
let mut screen_height = 0;
let mut screen_width = 0;
loop {
let new_screen_height = getmaxy(stdscr());
let new_screen_width = getmaxx(stdscr());
if screen_height != new_screen_height || screen_width != new_screen_width {
clear();
refresh();
screen_height = new_screen_height;
screen_width = new_screen_width;
utils::recreate_window(&mut error_window);
error_window.draw();
}
match get_wch() {
Some(wch) => match wch {
WchResult::KeyCode(code) => match code {
KEY_SELECT | KEY_ENTER => {
break;
}
_ => (),
},
WchResult::Char(c) => match char::from_u32(c) {
Some(c) => match c {
'\n' | '\r' => break,
'X' | 'x' => exit_regular(),
_ => (),
},
None => (),
},
},
None => (),
}
}
error_window.del();
}
fn exit_unsuccessful(error: Error) -> ! {
endwin();
eprintln!("⛔ {}", error);
exit(1)
}
fn exit_regular() {
endwin();
exit(0);
}