Support font setup. Small improvements

This commit is contained in:
daa 2017-03-07 00:05:48 +03:00
parent fb8c55a4f0
commit 7f2e5835e4
3 changed files with 107 additions and 117 deletions

View File

@ -1,2 +1,8 @@
# neovim-gtk # neovim-gtk
gtk ui for neovim written in rust. Use gtk-rs bindings. Because gtk-rs bindins still in development, this gui used toy cairo font api. GTK ui for neovim written in rust using gtk-rs bindings.
## Font settings
To setup font call:
```
call rpcnotify(1, 'Gui', 'Font', 'DejaVu Sans Mono 12')
```

View File

@ -37,6 +37,10 @@ pub trait RedrawEvents {
fn on_mouse_off(&mut self); fn on_mouse_off(&mut self);
} }
pub trait GuiApi {
fn set_font(&mut self, font_desc: &str);
}
macro_rules! try_str { macro_rules! try_str {
($exp:expr) => (match $exp { ($exp:expr) => (match $exp {
Value::String(ref val) => val, Value::String(ref val) => val,
@ -79,16 +83,18 @@ pub fn initialize(ui: &mut Ui) -> Result<()> {
} }
fn nvim_cb(method: &str, params: Vec<Value>) { fn nvim_cb(method: &str, params: Vec<Value>) {
if method == "redraw" { match method {
for ev in params { "redraw" => {
if let Value::Array(ev_args) = ev { safe_call(move |ui| {
for ev in &params {
if let &Value::Array(ref ev_args) = ev {
if let Value::String(ref ev_name) = ev_args[0] { if let Value::String(ref ev_name) = ev_args[0] {
for ref local_args in ev_args.iter().skip(1) { for ref local_args in ev_args.iter().skip(1) {
let args = match *local_args { let args = match *local_args {
&Value::Array(ref ar) => ar.clone(), &Value::Array(ref ar) => ar.clone(),
_ => vec![], _ => vec![],
}; };
call(ev_name, args); call(ui, ev_name, &args)?;
} }
} else { } else {
println!("Unsupported event {:?}", ev_args); println!("Unsupported event {:?}", ev_args);
@ -98,43 +104,47 @@ fn nvim_cb(method: &str, params: Vec<Value>) {
} }
} }
ui.on_redraw();
Ok(())
});
}
"Gui" => {
if params.len() > 0 {
if let Value::String(ev_name) = params[0].clone() {
let args = params.iter().skip(1).cloned().collect();
safe_call(move |ui| { safe_call(move |ui| {
call_gui_event(ui, &ev_name, &args)?;
ui.on_redraw(); ui.on_redraw();
Ok(()) Ok(())
}); });
} else { } else {
println!("Notification {}", method); println!("Unsupported event {:?}", params);
}
} else {
println!("Unsupported event {:?}", params);
}
}
_ => {
println!("Notification {}({:?})", method, params);
}
} }
} }
fn call(method: &str, args: Vec<Value>) { fn call_gui_event(ui: &mut Ui, method: &str, args: &Vec<Value>) -> result::Result<(), String> {
match method { match method {
"cursor_goto" => { "Font" => ui.set_font(try_str!(args[0])),
safe_call(move |ui| { _ => return Err(format!("Unsupported event {}({:?})", method, args)),
ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1]));
Ok(())
})
} }
"put" => {
safe_call(move |ui| {
ui.on_put(try_str!(args[0]));
Ok(()) Ok(())
}) }
}
"clear" => { fn call(ui: &mut Ui, method: &str, args: &Vec<Value>) -> result::Result<(), String> {
safe_call(move |ui| { match method {
ui.on_clear(); "cursor_goto" => ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1])),
Ok(()) "put" => ui.on_put(try_str!(args[0])),
}) "clear" => ui.on_clear(),
} "resize" => ui.on_resize(try_uint!(args[0]), try_uint!(args[1])),
"resize" => {
safe_call(move |ui| {
ui.on_resize(try_uint!(args[0]), try_uint!(args[1]));
Ok(())
});
}
"highlight_set" => { "highlight_set" => {
safe_call(move |ui| {
if let Value::Map(ref attrs) = args[0] { if let Value::Map(ref attrs) = args[0] {
let attrs_map: HashMap<String, Value> = attrs.iter() let attrs_map: HashMap<String, Value> = attrs.iter()
.map(|v| match v { .map(|v| match v {
@ -146,62 +156,24 @@ fn call(method: &str, args: Vec<Value>) {
} else { } else {
panic!("Supports only map value as argument"); panic!("Supports only map value as argument");
} }
Ok(())
});
}
"eol_clear" => {
safe_call(move |ui| {
ui.on_eol_clear();
Ok(())
})
} }
"eol_clear" => ui.on_eol_clear(),
"set_scroll_region" => { "set_scroll_region" => {
safe_call(move |ui| {
ui.on_set_scroll_region(try_uint!(args[0]), ui.on_set_scroll_region(try_uint!(args[0]),
try_uint!(args[1]), try_uint!(args[1]),
try_uint!(args[2]), try_uint!(args[2]),
try_uint!(args[3])); try_uint!(args[3]));
Ok(())
});
}
"scroll" => {
safe_call(move |ui| {
ui.on_scroll(try_int!(args[0]));
Ok(())
});
}
"update_bg" => {
safe_call(move |ui| {
ui.on_update_bg(try_int!(args[0]));
Ok(())
});
}
"update_fg" => {
safe_call(move |ui| {
ui.on_update_fg(try_int!(args[0]));
Ok(())
});
}
"mode_change" => {
safe_call(move |ui| {
ui.on_mode_change(try_str!(args[0]));
Ok(())
});
}
"mouse_on" => {
safe_call(move |ui| {
ui.on_mouse_on();
Ok(())
});
}
"mouse_off" => {
safe_call(move |ui| {
ui.on_mouse_off();
Ok(())
});
} }
"scroll" => ui.on_scroll(try_int!(args[0])),
"update_bg" => ui.on_update_bg(try_int!(args[0])),
"update_fg" => ui.on_update_fg(try_int!(args[0])),
"mode_change" => ui.on_mode_change(try_str!(args[0])),
"mouse_on" => ui.on_mouse_on(),
"mouse_off" => ui.on_mouse_off(),
_ => println!("Event {}({:?})", method, args), _ => println!("Event {}({:?})", method, args),
}; };
Ok(())
} }
fn safe_call<F>(cb: F) fn safe_call<F>(cb: F)

View File

@ -16,7 +16,7 @@ use glib;
use neovim_lib::{Neovim, NeovimApi, Value, Integer}; use neovim_lib::{Neovim, NeovimApi, Value, Integer};
use ui_model::{UiModel, Attrs, Color, COLOR_BLACK, COLOR_WHITE}; use ui_model::{UiModel, Attrs, Color, COLOR_BLACK, COLOR_WHITE};
use nvim::RedrawEvents; use nvim::{RedrawEvents, GuiApi};
use input::{convert_key, keyval_to_input_string}; use input::{convert_key, keyval_to_input_string};
@ -55,6 +55,7 @@ pub struct Ui {
mode: NvimMode, mode: NvimMode,
mouse_enabled: bool, mouse_enabled: bool,
mouse_pressed: bool, mouse_pressed: bool,
font_desc: String,
} }
impl Ui { impl Ui {
@ -73,6 +74,7 @@ impl Ui {
mode: NvimMode::Normal, mode: NvimMode::Normal,
mouse_enabled: false, mouse_enabled: false,
mouse_pressed: false, mouse_pressed: false,
font_desc: FONT_NAME.to_owned(),
} }
} }
@ -135,6 +137,14 @@ impl Ui {
window.set_title("Neovim-gtk"); window.set_title("Neovim-gtk");
self.drawing_area.connect_configure_event(gtk_configure_event); self.drawing_area.connect_configure_event(gtk_configure_event);
} }
fn create_pango_font(&self) -> FontDescription {
FontDescription::from_string(&self.font_desc)
}
fn set_font_desc(&mut self, desc: &str) {
self.font_desc = desc.to_owned();
}
} }
fn gtk_button_press(_: &DrawingArea, ev: &EventButton) -> Inhibit { fn gtk_button_press(_: &DrawingArea, ev: &EventButton) -> Inhibit {
@ -217,7 +227,7 @@ fn gtk_draw(_: &DrawingArea, ctx: &cairo::Context) -> Inhibit {
UI.with(|ui_cell| { UI.with(|ui_cell| {
let mut ui = ui_cell.borrow_mut(); let mut ui = ui_cell.borrow_mut();
let (width, height) = calc_char_bounds(ctx); let (width, height) = calc_char_bounds(&*ui, ctx);
ui.line_height = Some(height as f64); ui.line_height = Some(height as f64);
ui.char_width = Some(width as f64); ui.char_width = Some(width as f64);
@ -260,10 +270,6 @@ fn gtk_configure_event(_: &DrawingArea, ev: &EventConfigure) -> bool {
false false
} }
fn font_description() -> FontDescription {
FontDescription::from_string(FONT_NAME)
}
fn draw(ui: &Ui, ctx: &cairo::Context) { fn draw(ui: &Ui, ctx: &cairo::Context) {
ctx.set_source_rgb(ui.bg_color.0, ui.bg_color.1, ui.bg_color.2); ctx.set_source_rgb(ui.bg_color.0, ui.bg_color.1, ui.bg_color.2);
ctx.paint(); ctx.paint();
@ -319,7 +325,7 @@ fn draw(ui: &Ui, ctx: &cairo::Context) {
} }
if !cell.ch.is_whitespace() { if !cell.ch.is_whitespace() {
let mut desc = font_description(); let mut desc = ui.create_pango_font();
if cell.attrs.italic { if cell.attrs.italic {
desc.set_style(pango::Style::Italic); desc.set_style(pango::Style::Italic);
} }
@ -346,10 +352,10 @@ fn draw(ui: &Ui, ctx: &cairo::Context) {
} }
fn calc_char_bounds(ctx: &cairo::Context) -> (i32, i32) { fn calc_char_bounds(ui: &Ui, ctx: &cairo::Context) -> (i32, i32) {
let layout = pc::create_layout(ctx); let layout = pc::create_layout(ctx);
let desc = font_description(); let desc = ui.create_pango_font();
layout.set_font_description(Some(&desc)); layout.set_font_description(Some(&desc));
layout.set_text("A", -1); layout.set_text("A", -1);
@ -375,6 +381,12 @@ fn request_width(ui: &Ui) {
} }
} }
impl GuiApi for Ui {
fn set_font(&mut self, font_desc: &str) {
self.set_font_desc(font_desc);
}
}
impl RedrawEvents for Ui { impl RedrawEvents for Ui {
fn on_cursor_goto(&mut self, row: u64, col: u64) { fn on_cursor_goto(&mut self, row: u64, col: u64) {
self.model.set_cursor(row, col); self.model.set_cursor(row, col);