neovim-gtk/src/ui.rs

149 lines
4.1 KiB
Rust
Raw Normal View History

2016-03-31 10:09:34 +00:00
use std::cell::RefCell;
use std::thread;
2016-03-16 15:25:25 +00:00
use cairo;
use gtk;
use gtk::prelude::*;
2016-03-17 13:58:21 +00:00
use gtk::{Window, WindowType, DrawingArea, Grid, ToolButton, ButtonBox, Orientation, Image};
2016-03-31 13:52:22 +00:00
use gdk;
use gdk::EventKey;
use neovim_lib::{Neovim, NeovimApi};
2016-03-16 15:25:25 +00:00
2016-03-19 08:47:23 +00:00
use ui_model::UiModel;
2016-03-23 11:59:18 +00:00
use nvim::RedrawEvents;
2016-03-19 08:47:23 +00:00
2016-03-31 10:09:34 +00:00
thread_local!(pub static UI: RefCell<Ui> = {
let thread = thread::current();
let current_thread_name = thread.name();
if current_thread_name != Some("<main>") {
panic!("Can create UI only from main thread, {:?}", current_thread_name);
}
RefCell::new(Ui::new())
});
2016-03-19 10:27:39 +00:00
pub struct Ui {
2016-03-28 15:05:10 +00:00
pub model: UiModel,
nvim: Option<Neovim>,
2016-03-31 10:09:34 +00:00
drawing_area: DrawingArea,
2016-03-19 10:27:39 +00:00
}
2016-03-16 15:25:25 +00:00
impl Ui {
pub fn new() -> Ui {
2016-03-19 10:27:39 +00:00
Ui {
model: UiModel::empty(),
2016-03-31 10:09:34 +00:00
drawing_area: DrawingArea::new(),
nvim: None,
2016-03-19 10:27:39 +00:00
}
2016-03-16 15:25:25 +00:00
}
pub fn set_nvim(&mut self, nvim: Neovim) {
self.nvim = Some(nvim);
}
pub fn nvim(&mut self) -> &mut Neovim {
self.nvim.as_mut().unwrap()
}
2016-03-31 10:09:34 +00:00
pub fn init(&mut self) {
2016-03-16 15:25:25 +00:00
let window = Window::new(WindowType::Toplevel);
let grid = Grid::new();
let button_bar = ButtonBox::new(Orientation::Horizontal);
2016-03-17 13:58:21 +00:00
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);
2016-03-16 15:25:25 +00:00
grid.attach(&button_bar, 0, 0, 1, 1);
2016-03-31 10:09:34 +00:00
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);
2016-03-16 15:25:25 +00:00
window.add(&grid);
window.show_all();
2016-03-31 13:52:22 +00:00
window.connect_key_press_event(gtk_key_press);
2016-03-31 10:09:34 +00:00
window.connect_delete_event(|_, _| {
2016-03-16 15:25:25 +00:00
gtk::main_quit();
Inhibit(false)
});
}
2016-03-31 10:09:34 +00:00
}
2016-03-16 15:25:25 +00:00
2016-03-31 13:52:22 +00:00
fn gtk_key_press(_: &Window, ev: &EventKey) -> Inhibit {
let keyval = ev.get_keyval();
if let Some(keyval_name) = gdk::keyval_name(keyval) {
UI.with(|ui_cell| {
let mut ui = ui_cell.borrow_mut();
let input = if keyval_name.starts_with("KP_") {
keyval_name.chars().skip(3).collect()
} else {
keyval_name
};
ui.nvim().input(&input).expect("Error run input command to nvim");
});
}
Inhibit(true)
}
2016-03-31 10:09:34 +00:00
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);
2016-03-31 13:52:22 +00:00
let font_extents = ctx.font_extents();
2016-03-31 10:09:34 +00:00
UI.with(|ui_cell| {
let ui = ui_cell.borrow();
2016-03-31 13:52:22 +00:00
ctx.set_source_rgb(0.0, 0.0, 0.0);
let mut line_y = font_extents.height;
2016-03-31 10:09:34 +00:00
for line in ui.model.lines() {
ctx.move_to(0.0, line_y);
ctx.show_text(&line);
2016-03-31 13:52:22 +00:00
line_y += font_extents.height;
2016-03-31 10:09:34 +00:00
}
});
Inhibit(true)
2016-03-16 15:25:25 +00:00
}
2016-03-23 11:59:18 +00:00
impl RedrawEvents for Ui {
2016-03-28 14:03:21 +00:00
fn on_cursor_goto(&mut self, row: u64, col: u64) {
self.model.set_cursor(row, col);
}
2016-03-28 15:05:10 +00:00
fn on_put(&mut self, text: &str) {
self.model.put(text);
}
2016-03-29 09:22:16 +00:00
fn on_clear(&mut self) {
self.model.clear();
}
2016-03-29 09:43:01 +00:00
fn on_resize(&mut self, columns: u64, rows: u64) {
self.model = UiModel::new(rows, columns);
}
2016-03-31 13:52:22 +00:00
fn on_redraw(&self) {
self.drawing_area.queue_draw();
}
2016-03-23 11:59:18 +00:00
}