2017-03-22 10:05:10 +00:00
|
|
|
use cairo;
|
|
|
|
use ui_model::Color;
|
2017-04-12 10:12:05 +00:00
|
|
|
use ui::UiMutex;
|
|
|
|
use shell;
|
|
|
|
use shell::NvimMode;
|
2017-03-24 19:23:22 +00:00
|
|
|
use nvim::{RepaintMode, RedrawEvents};
|
2017-04-12 10:12:05 +00:00
|
|
|
use std::sync::{Arc, Weak};
|
2017-03-22 10:05:10 +00:00
|
|
|
|
2017-03-22 15:37:34 +00:00
|
|
|
use glib;
|
|
|
|
|
2017-03-23 15:04:24 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-31 09:49:14 +00:00
|
|
|
#[derive(PartialEq)]
|
2017-03-23 15:04:24 +00:00
|
|
|
enum AnimPhase {
|
2017-03-24 20:34:03 +00:00
|
|
|
Shown,
|
2017-03-23 15:04:24 +00:00
|
|
|
Hide,
|
2017-03-24 20:34:03 +00:00
|
|
|
Hidden,
|
2017-03-23 15:04:24 +00:00
|
|
|
Show,
|
2017-03-31 09:49:14 +00:00
|
|
|
NoFocus,
|
2017-04-03 15:16:04 +00:00
|
|
|
Busy,
|
2017-03-23 15:04:24 +00:00
|
|
|
}
|
|
|
|
|
2017-03-25 21:38:22 +00:00
|
|
|
struct State {
|
2017-03-23 15:04:24 +00:00
|
|
|
alpha: Alpha,
|
|
|
|
anim_phase: AnimPhase,
|
2017-04-12 10:12:05 +00:00
|
|
|
shell: Weak<UiMutex<shell::State>>,
|
2017-03-24 20:34:03 +00:00
|
|
|
|
|
|
|
timer: Option<glib::SourceId>,
|
2017-03-23 15:04:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl State {
|
2017-04-12 10:12:05 +00:00
|
|
|
fn new(shell: Weak<UiMutex<shell::State>>) -> State {
|
2017-03-24 19:23:22 +00:00
|
|
|
State {
|
2017-03-23 15:04:24 +00:00
|
|
|
alpha: Alpha(1.0),
|
2017-03-24 20:34:03 +00:00
|
|
|
anim_phase: AnimPhase::Shown,
|
2017-04-12 10:12:05 +00:00
|
|
|
shell: shell,
|
2017-03-24 20:34:03 +00:00
|
|
|
timer: None,
|
2017-03-23 15:04:24 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-25 21:38:22 +00:00
|
|
|
|
2017-03-31 09:49:14 +00:00
|
|
|
fn reset_to(&mut self, phase: AnimPhase) {
|
2017-03-25 21:38:22 +00:00
|
|
|
self.alpha = Alpha(1.0);
|
2017-03-31 09:49:14 +00:00
|
|
|
self.anim_phase = phase;
|
|
|
|
if let Some(timer_id) = self.timer {
|
|
|
|
glib::source_remove(timer_id);
|
|
|
|
self.timer = None;
|
|
|
|
}
|
2017-03-25 21:38:22 +00:00
|
|
|
}
|
2017-03-23 15:04:24 +00:00
|
|
|
}
|
|
|
|
|
2017-03-22 10:05:10 +00:00
|
|
|
pub struct Cursor {
|
2017-03-26 11:34:38 +00:00
|
|
|
state: Arc<UiMutex<State>>,
|
2017-03-22 10:05:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Cursor {
|
2017-04-12 10:12:05 +00:00
|
|
|
pub fn new(shell: Weak<UiMutex<shell::State>>) -> Cursor {
|
|
|
|
Cursor { state: Arc::new(UiMutex::new(State::new(shell))) }
|
2017-03-23 15:04:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn start(&mut self) {
|
2017-03-24 20:34:03 +00:00
|
|
|
let state = self.state.clone();
|
2017-03-26 11:34:38 +00:00
|
|
|
let mut mut_state = self.state.borrow_mut();
|
2017-03-31 09:49:14 +00:00
|
|
|
mut_state.reset_to(AnimPhase::Shown);
|
2017-03-25 21:38:22 +00:00
|
|
|
mut_state.timer = Some(glib::timeout_add(500, move || anim_step(&state)));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn reset_state(&mut self) {
|
|
|
|
self.start();
|
2017-03-22 10:05:10 +00:00
|
|
|
}
|
2017-04-12 10:12:05 +00:00
|
|
|
|
2017-03-31 09:49:14 +00:00
|
|
|
pub fn enter_focus(&mut self) {
|
|
|
|
self.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn leave_focus(&mut self) {
|
|
|
|
self.state.borrow_mut().reset_to(AnimPhase::NoFocus);
|
|
|
|
}
|
2017-03-22 10:05:10 +00:00
|
|
|
|
2017-04-03 15:16:04 +00:00
|
|
|
pub fn busy_on(&mut self) {
|
|
|
|
self.state.borrow_mut().reset_to(AnimPhase::Busy);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn busy_off(&mut self) {
|
|
|
|
self.start();
|
|
|
|
}
|
|
|
|
|
2017-03-24 19:23:22 +00:00
|
|
|
pub fn draw(&self,
|
|
|
|
ctx: &cairo::Context,
|
2017-04-12 10:12:05 +00:00
|
|
|
shell: &shell::State,
|
2017-03-24 19:23:22 +00:00
|
|
|
char_width: f64,
|
|
|
|
line_height: f64,
|
|
|
|
line_y: f64,
|
|
|
|
double_width: bool,
|
|
|
|
bg: &Color) {
|
2017-03-23 15:04:24 +00:00
|
|
|
|
2017-03-26 11:34:38 +00:00
|
|
|
let state = self.state.borrow();
|
2017-04-03 15:16:04 +00:00
|
|
|
|
|
|
|
if state.anim_phase == AnimPhase::Busy {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let current_point = ctx.get_current_point();
|
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);
|
2017-03-31 09:49:14 +00:00
|
|
|
if state.anim_phase == AnimPhase::NoFocus {
|
|
|
|
ctx.stroke();
|
|
|
|
} else {
|
|
|
|
ctx.fill();
|
|
|
|
}
|
2017-03-22 10:05:10 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-22 15:37:34 +00:00
|
|
|
|
2017-03-26 11:34:38 +00:00
|
|
|
fn anim_step(state: &Arc<UiMutex<State>>) -> glib::Continue {
|
|
|
|
let mut mut_state = state.borrow_mut();
|
2017-03-24 20:34:03 +00:00
|
|
|
|
|
|
|
let next_event = match mut_state.anim_phase {
|
|
|
|
AnimPhase::Shown => {
|
|
|
|
mut_state.anim_phase = AnimPhase::Hide;
|
2017-03-25 21:38:22 +00:00
|
|
|
Some(60)
|
2017-03-24 20:34:03 +00:00
|
|
|
}
|
|
|
|
AnimPhase::Hide => {
|
|
|
|
if !mut_state.alpha.hide(0.3) {
|
|
|
|
mut_state.anim_phase = AnimPhase::Hidden;
|
|
|
|
|
|
|
|
Some(300)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AnimPhase::Hidden => {
|
|
|
|
mut_state.anim_phase = AnimPhase::Show;
|
|
|
|
|
2017-03-25 21:38:22 +00:00
|
|
|
Some(60)
|
2017-03-24 20:34:03 +00:00
|
|
|
}
|
|
|
|
AnimPhase::Show => {
|
|
|
|
if !mut_state.alpha.show(0.3) {
|
|
|
|
mut_state.anim_phase = AnimPhase::Shown;
|
|
|
|
|
|
|
|
Some(500)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2017-03-31 09:49:14 +00:00
|
|
|
AnimPhase::NoFocus => None,
|
2017-04-03 15:16:04 +00:00
|
|
|
AnimPhase::Busy => None,
|
2017-03-24 20:34:03 +00:00
|
|
|
};
|
|
|
|
|
2017-04-12 10:12:05 +00:00
|
|
|
let shell = mut_state.shell.upgrade().unwrap();
|
|
|
|
let shell = shell.borrow();
|
|
|
|
let point = shell.model.cur_point();
|
|
|
|
shell.on_redraw(&RepaintMode::Area(point));
|
2017-03-24 20:34:03 +00:00
|
|
|
|
2017-03-25 21:38:22 +00:00
|
|
|
|
2017-03-24 20:34:03 +00:00
|
|
|
if let Some(timeout) = next_event {
|
2017-04-12 10:12:05 +00:00
|
|
|
let moved_state = state.clone();
|
2017-03-25 21:38:22 +00:00
|
|
|
mut_state.timer = Some(glib::timeout_add(timeout, move || anim_step(&moved_state)));
|
2017-03-24 20:34:03 +00:00
|
|
|
|
|
|
|
glib::Continue(false)
|
|
|
|
} else {
|
|
|
|
glib::Continue(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-03-23 15:04:24 +00:00
|
|
|
impl Drop for Cursor {
|
|
|
|
fn drop(&mut self) {
|
2017-03-26 11:34:38 +00:00
|
|
|
if let Some(timer_id) = self.state.borrow().timer {
|
2017-03-23 15:04:24 +00:00
|
|
|
glib::source_remove(timer_id);
|
2017-03-22 15:37:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|