neovim-gtk/src/cursor.rs

163 lines
3.9 KiB
Rust
Raw Normal View History

2017-03-22 10:05:10 +00:00
use cairo;
use ui_model::Color;
use ui::UI;
2017-03-22 10:05:10 +00:00
use shell::{Shell, NvimMode};
2017-03-24 19:23:22 +00:00
use nvim::{RepaintMode, RedrawEvents};
use std::sync::{Arc, Mutex};
2017-03-22 10:05:10 +00:00
2017-03-22 15:37:34 +00:00
use glib;
struct Alpha(f64);
impl Alpha {
pub fn show(&mut self, step: f64) -> bool {
self.0 += step;
if self.0 > 1.0 {
self.0 = 1.0;
false
} else {
true
}
}
pub fn hide(&mut self, step: f64) -> bool {
self.0 -= step;
if self.0 < 0.0 {
self.0 = 0.0;
false
} else {
true
}
}
}
enum AnimPhase {
2017-03-24 19:23:22 +00:00
Shown(i32),
Hide,
2017-03-24 19:23:22 +00:00
Hidden(i32),
Show,
}
2017-03-24 19:23:22 +00:00
impl AnimPhase {
fn sub(&mut self, step: i32) -> bool {
match self {
&mut AnimPhase::Shown(ref mut val) |
&mut AnimPhase::Hidden(ref mut val) => {
*val -= step;
if *val <= 0 {
false
} else {
true
}
}
_ => false,
}
}
}
pub struct State {
alpha: Alpha,
anim_phase: AnimPhase,
}
impl State {
pub fn new() -> State {
2017-03-24 19:23:22 +00:00
State {
alpha: Alpha(1.0),
2017-03-24 19:23:22 +00:00
anim_phase: AnimPhase::Shown(500),
}
}
}
2017-03-22 10:05:10 +00:00
pub struct Cursor {
timer: Option<glib::SourceId>,
state: Arc<Mutex<State>>,
2017-03-22 10:05:10 +00:00
}
impl Cursor {
pub fn new() -> Cursor {
2017-03-24 19:23:22 +00:00
Cursor {
timer: None,
state: Arc::new(Mutex::new(State::new())),
}
}
pub fn start(&mut self) {
if self.timer.is_none() {
let state = self.state.clone();
self.timer = Some(glib::timeout_add(100, move || {
let mut mut_state = state.lock().unwrap();
2017-03-24 19:23:22 +00:00
// wait
// [TODO]: Implement wait through new timeout - 2017-03-24 10:21
if mut_state.anim_phase.sub(100) {
return glib::Continue(true);
}
match mut_state.anim_phase {
2017-03-24 19:23:22 +00:00
AnimPhase::Shown(_) => {
mut_state.anim_phase = AnimPhase::Hide;
}
AnimPhase::Hide => {
2017-03-24 19:23:22 +00:00
if !mut_state.alpha.hide(0.3) {
mut_state.anim_phase = AnimPhase::Hidden(300);
}
}
2017-03-24 19:23:22 +00:00
AnimPhase::Hidden(_) => {
mut_state.anim_phase = AnimPhase::Show;
}
AnimPhase::Show => {
2017-03-24 19:23:22 +00:00
if !mut_state.alpha.show(0.3) {
mut_state.anim_phase = AnimPhase::Shown(500);
}
}
}
SHELL!(&shell = {
2017-03-24 19:23:22 +00:00
let point = shell.model.cur_point();
shell.on_redraw(&RepaintMode::Area(point));
});
glib::Continue(true)
}));
}
2017-03-22 10:05:10 +00:00
}
2017-03-24 19:23:22 +00:00
pub fn draw(&self,
ctx: &cairo::Context,
shell: &Shell,
char_width: f64,
line_height: f64,
line_y: f64,
double_width: bool,
bg: &Color) {
2017-03-22 10:05:10 +00:00
let current_point = ctx.get_current_point();
let state = self.state.lock().unwrap();
2017-03-24 19:23:22 +00:00
ctx.set_source_rgba(1.0 - bg.0, 1.0 - bg.1, 1.0 - bg.2, 0.6 * state.alpha.0);
2017-03-22 10:05:10 +00:00
let cursor_width = if shell.mode == NvimMode::Insert {
char_width / 5.0
} else {
if double_width {
char_width * 2.0
} else {
char_width
}
};
ctx.rectangle(current_point.0, line_y, cursor_width, line_height);
ctx.fill();
}
}
2017-03-22 15:37:34 +00:00
impl Drop for Cursor {
fn drop(&mut self) {
if let Some(timer_id) = self.timer {
glib::source_remove(timer_id);
2017-03-22 15:37:34 +00:00
}
}
}