From 7f2e5835e4b0877486336bc70964b93bcea807c2 Mon Sep 17 00:00:00 2001 From: daa Date: Tue, 7 Mar 2017 00:05:48 +0300 Subject: [PATCH] Support font setup. Small improvements --- README.md | 8 ++- src/nvim.rs | 186 ++++++++++++++++++++++------------------------------ src/ui.rs | 30 ++++++--- 3 files changed, 107 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index f13a605..7e71de8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ # 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') +``` diff --git a/src/nvim.rs b/src/nvim.rs index c11857e..031257d 100644 --- a/src/nvim.rs +++ b/src/nvim.rs @@ -37,6 +37,10 @@ pub trait RedrawEvents { fn on_mouse_off(&mut self); } +pub trait GuiApi { + fn set_font(&mut self, font_desc: &str); +} + macro_rules! try_str { ($exp:expr) => (match $exp { Value::String(ref val) => val, @@ -79,129 +83,97 @@ pub fn initialize(ui: &mut Ui) -> Result<()> { } fn nvim_cb(method: &str, params: Vec) { - if method == "redraw" { - for ev in params { - if let Value::Array(ev_args) = ev { - if let Value::String(ref ev_name) = ev_args[0] { - for ref local_args in ev_args.iter().skip(1) { - let args = match *local_args { - &Value::Array(ref ar) => ar.clone(), - _ => vec![], - }; - call(ev_name, args); + match method { + "redraw" => { + safe_call(move |ui| { + for ev in ¶ms { + if let &Value::Array(ref ev_args) = ev { + if let Value::String(ref ev_name) = ev_args[0] { + for ref local_args in ev_args.iter().skip(1) { + let args = match *local_args { + &Value::Array(ref ar) => ar.clone(), + _ => vec![], + }; + call(ui, ev_name, &args)?; + } + } else { + println!("Unsupported event {:?}", ev_args); + } + } else { + println!("Unsupported event type {:?}", ev); } + } + + 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| { + call_gui_event(ui, &ev_name, &args)?; + ui.on_redraw(); + Ok(()) + }); } else { - println!("Unsupported event {:?}", ev_args); + println!("Unsupported event {:?}", params); } } else { - println!("Unsupported event type {:?}", ev); + println!("Unsupported event {:?}", params); } } - - safe_call(move |ui| { - ui.on_redraw(); - Ok(()) - }); - } else { - println!("Notification {}", method); + _ => { + println!("Notification {}({:?})", method, params); + } } } -fn call(method: &str, args: Vec) { +fn call_gui_event(ui: &mut Ui, method: &str, args: &Vec) -> result::Result<(), String> { match method { - "cursor_goto" => { - safe_call(move |ui| { - 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(()) - }) - } - "clear" => { - safe_call(move |ui| { - ui.on_clear(); - Ok(()) - }) - } - "resize" => { - safe_call(move |ui| { - ui.on_resize(try_uint!(args[0]), try_uint!(args[1])); - Ok(()) - }); - } + "Font" => ui.set_font(try_str!(args[0])), + _ => return Err(format!("Unsupported event {}({:?})", method, args)), + } + Ok(()) +} + +fn call(ui: &mut Ui, method: &str, args: &Vec) -> result::Result<(), String> { + match method { + "cursor_goto" => ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1])), + "put" => ui.on_put(try_str!(args[0])), + "clear" => ui.on_clear(), + "resize" => ui.on_resize(try_uint!(args[0]), try_uint!(args[1])), "highlight_set" => { - safe_call(move |ui| { - if let Value::Map(ref attrs) = args[0] { - let attrs_map: HashMap = attrs.iter() - .map(|v| match v { - &(Value::String(ref key), ref value) => (key.clone(), value.clone()), - _ => panic!("attribute key must be string"), - }) - .collect(); - ui.on_highlight_set(&attrs_map); - } else { - panic!("Supports only map value as argument"); - } - Ok(()) - }); - } - "eol_clear" => { - safe_call(move |ui| { - ui.on_eol_clear(); - Ok(()) - }) + if let Value::Map(ref attrs) = args[0] { + let attrs_map: HashMap = attrs.iter() + .map(|v| match v { + &(Value::String(ref key), ref value) => (key.clone(), value.clone()), + _ => panic!("attribute key must be string"), + }) + .collect(); + ui.on_highlight_set(&attrs_map); + } else { + panic!("Supports only map value as argument"); + } } + "eol_clear" => ui.on_eol_clear(), "set_scroll_region" => { - safe_call(move |ui| { - ui.on_set_scroll_region(try_uint!(args[0]), - try_uint!(args[1]), - try_uint!(args[2]), - 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(()) - }); + ui.on_set_scroll_region(try_uint!(args[0]), + try_uint!(args[1]), + try_uint!(args[2]), + try_uint!(args[3])); } + "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), }; + + Ok(()) } fn safe_call(cb: F) diff --git a/src/ui.rs b/src/ui.rs index ba72fbf..1c648ae 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -16,7 +16,7 @@ use glib; use neovim_lib::{Neovim, NeovimApi, Value, Integer}; 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}; @@ -55,6 +55,7 @@ pub struct Ui { mode: NvimMode, mouse_enabled: bool, mouse_pressed: bool, + font_desc: String, } impl Ui { @@ -73,6 +74,7 @@ impl Ui { mode: NvimMode::Normal, mouse_enabled: false, mouse_pressed: false, + font_desc: FONT_NAME.to_owned(), } } @@ -135,6 +137,14 @@ impl Ui { window.set_title("Neovim-gtk"); 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 { @@ -217,7 +227,7 @@ fn gtk_draw(_: &DrawingArea, ctx: &cairo::Context) -> Inhibit { UI.with(|ui_cell| { 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.char_width = Some(width as f64); @@ -260,10 +270,6 @@ fn gtk_configure_event(_: &DrawingArea, ev: &EventConfigure) -> bool { false } -fn font_description() -> FontDescription { - FontDescription::from_string(FONT_NAME) -} - fn draw(ui: &Ui, ctx: &cairo::Context) { ctx.set_source_rgb(ui.bg_color.0, ui.bg_color.1, ui.bg_color.2); ctx.paint(); @@ -319,7 +325,7 @@ fn draw(ui: &Ui, ctx: &cairo::Context) { } if !cell.ch.is_whitespace() { - let mut desc = font_description(); + let mut desc = ui.create_pango_font(); if cell.attrs.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 desc = font_description(); + let desc = ui.create_pango_font(); layout.set_font_description(Some(&desc)); 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 { fn on_cursor_goto(&mut self, row: u64, col: u64) { self.model.set_cursor(row, col);