use std::cell::RefCell; use std::thread; use cairo; use gtk; use gtk::prelude::*; use gtk::{Window, WindowType, DrawingArea, Grid, ToolButton, ButtonBox, Orientation, Image}; use neovim_lib::Neovim; use ui_model::UiModel; use nvim::RedrawEvents; thread_local!(pub static UI: RefCell = { let thread = thread::current(); let current_thread_name = thread.name(); if current_thread_name != Some("
") { panic!("Can create UI only from main thread, {:?}", current_thread_name); } RefCell::new(Ui::new()) }); pub struct Ui { pub model: UiModel, nvim: Option, drawing_area: DrawingArea, } impl Ui { pub fn new() -> Ui { Ui { model: UiModel::empty(), drawing_area: DrawingArea::new(), nvim: None, } } pub fn set_nvim(&mut self, nvim: Neovim) { self.nvim = Some(nvim); } pub fn nvim(&mut self) -> &mut Neovim { self.nvim.as_mut().unwrap() } pub fn init(&mut self) { let window = Window::new(WindowType::Toplevel); let grid = Grid::new(); let button_bar = ButtonBox::new(Orientation::Horizontal); button_bar.set_hexpand(true); button_bar.set_layout(gtk::ButtonBoxStyle::Start); let open_image = Image::new_from_icon_name("document-open", 50); let open_btn = ToolButton::new(Some(&open_image), None); button_bar.add(&open_btn); let save_image = Image::new_from_icon_name("document-save", 50); let save_btn = ToolButton::new(Some(&save_image), None); button_bar.add(&save_btn); let exit_image = Image::new_from_icon_name("application-exit", 50); let exit_btn = ToolButton::new(Some(&exit_image), None); button_bar.add(&exit_btn); grid.attach(&button_bar, 0, 0, 1, 1); self.drawing_area.set_size_request(500, 500); self.drawing_area.set_hexpand(true); self.drawing_area.set_vexpand(true); grid.attach(&self.drawing_area, 0, 1, 1, 1); self.drawing_area.connect_draw(gtk_draw); window.add(&grid); window.show_all(); window.connect_delete_event(|_, _| { gtk::main_quit(); Inhibit(false) }); } } fn gtk_draw(drawing_area: &DrawingArea, ctx: &cairo::Context) -> Inhibit { let width = drawing_area.get_allocated_width() as f64; let height = drawing_area.get_allocated_height() as f64; let font_face = cairo::FontFace::toy_create("", cairo::enums::FontSlant::Normal, cairo::enums::FontWeight::Normal); ctx.set_font_face(font_face); UI.with(|ui_cell| { ctx.set_source_rgb(0.0, 0.0, 0.0); let ui = ui_cell.borrow(); let mut line_y = 30.0; for line in ui.model.lines() { ctx.move_to(0.0, line_y); ctx.show_text(&line); line_y += 30.0; } }); Inhibit(true) } impl RedrawEvents for Ui { fn on_cursor_goto(&mut self, row: u64, col: u64) { self.model.set_cursor(row, col); } fn on_put(&mut self, text: &str) { self.model.put(text); } fn on_clear(&mut self) { self.model.clear(); } fn on_resize(&mut self, columns: u64, rows: u64) { self.model = UiModel::new(rows, columns); } }