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
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);
}
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<Value>) {
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 &params {
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<Value>) {
fn call_gui_event(ui: &mut Ui, method: &str, args: &Vec<Value>) -> 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<Value>) -> 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<String, Value> = 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<String, Value> = 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<F>(cb: F)

View File

@ -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);