Draw gui cursor shape

This commit is contained in:
daa 2017-07-09 12:40:31 +03:00
parent 90dc2d4a53
commit 609d593db5
3 changed files with 123 additions and 21 deletions

View File

@ -3,6 +3,7 @@ use ui_model::Color;
use ui::UiMutex;
use shell;
use mode;
use nvim;
use nvim::{RepaintMode, RedrawEvents};
use std::sync::{Arc, Weak};
@ -123,7 +124,63 @@ impl Cursor {
let current_point = ctx.get_current_point();
ctx.set_source_rgba(1.0 - bg.0, 1.0 - bg.1, 1.0 - bg.2, 0.6 * state.alpha.0);
let cursor_width = if shell.mode.is(&mode::NvimMode::Insert) {
let (y, width, height) =
cursor_rect(&shell.mode, char_width, line_height, line_y, double_width);
ctx.rectangle(current_point.0, y, width, height);
if state.anim_phase == AnimPhase::NoFocus {
ctx.stroke();
} else {
ctx.fill();
}
}
}
fn cursor_rect(mode: &mode::Mode,
char_width: f64,
line_height: f64,
line_y: f64,
double_width: bool)
-> (f64, f64, f64) {
if let Some(mode_info) = mode.mode_info() {
match mode_info.cursor_shape() {
None |
Some(&nvim::CursorShape::Unknown) |
Some(&nvim::CursorShape::Block) => {
let cursor_width = if double_width {
char_width * 2.0
} else {
char_width
};
(line_y, cursor_width, line_height)
}
Some(&nvim::CursorShape::Vertical) => {
let cell_percentage = mode_info.cell_percentage();
let cursor_width = if cell_percentage > 0 {
(char_width * cell_percentage as f64) / 100.0
} else {
char_width
};
(line_y, cursor_width, line_height)
}
Some(&nvim::CursorShape::Horizontal) => {
let cell_percentage = mode_info.cell_percentage();
let cursor_width = if double_width {
char_width * 2.0
} else {
char_width
};
if cell_percentage > 0 {
let height = (line_height * cell_percentage as f64) / 100.0;
(line_y + line_height - height, cursor_width, height)
} else {
(line_y, cursor_width, line_height)
}
}
}
} else {
let cursor_width = if mode.is(&mode::NvimMode::Insert) {
char_width / 5.0
} else {
if double_width {
@ -133,15 +190,9 @@ impl Cursor {
}
};
ctx.rectangle(current_point.0, line_y, cursor_width, line_height);
if state.anim_phase == AnimPhase::NoFocus {
ctx.stroke();
} else {
ctx.fill();
}
(line_y, cursor_width, line_height)
}
}
fn anim_step(state: &Arc<UiMutex<State>>) -> glib::Continue {
let mut mut_state = state.borrow_mut();
@ -201,3 +252,62 @@ impl Drop for Cursor {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cursor_rect_horizontal() {
let mut mode = mode::Mode::new();
let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"),
From::from("horizontal")),
(From::from("cell_percentage"), From::from(25))]);
mode.update("insert", 0);
mode.set_info(true, vec![mode_info.unwrap()]);
let char_width = 50.0;
let line_height = 30.0;
let line_y = 0.0;
let (y, width, height) = cursor_rect(&mode, char_width, line_height, line_y, false);
assert_eq!(line_y + line_height - line_height / 4.0, y);
assert_eq!(char_width, width);
assert_eq!(line_height / 4.0, height);
}
#[test]
fn test_cursor_rect_horizontal_doublewidth() {
let mut mode = mode::Mode::new();
let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"),
From::from("horizontal")),
(From::from("cell_percentage"), From::from(25))]);
mode.update("insert", 0);
mode.set_info(true, vec![mode_info.unwrap()]);
let char_width = 50.0;
let line_height = 30.0;
let line_y = 0.0;
let (y, width, height) = cursor_rect(&mode, char_width, line_height, line_y, true);
assert_eq!(line_y + line_height - line_height / 4.0, y);
assert_eq!(char_width * 2.0, width);
assert_eq!(line_height / 4.0, height);
}
#[test]
fn test_cursor_rect_vertical() {
let mut mode = mode::Mode::new();
let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"),
From::from("vertical")),
(From::from("cell_percentage"), From::from(25))]);
mode.update("insert", 0);
mode.set_info(true, vec![mode_info.unwrap()]);
let char_width = 50.0;
let line_height = 30.0;
let line_y = 0.0;
let (y, width, height) = cursor_rect(&mode, char_width, line_height, line_y, false);
assert_eq!(line_y, y);
assert_eq!(char_width / 4.0, width);
assert_eq!(line_height, height);
}
}

View File

@ -26,11 +26,10 @@ impl Mode {
self.mode == *mode
}
pub fn mode_info(&self) -> nvim::ModeInfo {
pub fn mode_info(&self) -> Option<&nvim::ModeInfo> {
self.info
.as_ref()
.and_then(|i| i.get(self.idx).cloned())
.unwrap_or_else(nvim::ModeInfo::default)
.and_then(|i| i.get(self.idx))
}
pub fn update(&mut self, mode: &str, idx: usize) {

View File

@ -139,13 +139,6 @@ pub struct ModeInfo {
}
impl ModeInfo {
pub fn default() -> Self {
ModeInfo {
cursor_shape: Some(CursorShape::Block),
cell_percentage: None,
}
}
pub fn new(mode_info_arr: &Vec<(Value, Value)>) -> Result<Self, String> {
let mode_info_map = mode_info_arr.to_attrs_map()?;
@ -167,12 +160,12 @@ impl ModeInfo {
})
}
pub fn cursor_shape(&self) -> CursorShape {
self.cursor_shape.as_ref().cloned().unwrap_or(CursorShape::Block)
pub fn cursor_shape(&self) -> Option<&CursorShape> {
self.cursor_shape.as_ref()
}
pub fn cell_percentage(&self) -> u64 {
self.cell_percentage.unwrap_or(100)
self.cell_percentage.unwrap_or(0)
}
}