Support font setup. Small improvements
This commit is contained in:
parent
fb8c55a4f0
commit
7f2e5835e4
@ -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')
|
||||
```
|
||||
|
186
src/nvim.rs
186
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<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 ¶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<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)
|
||||
|
30
src/ui.rs
30
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);
|
||||
|
Loading…
Reference in New Issue
Block a user