Optimization of cursor animation

This commit is contained in:
daa 2017-03-24 23:34:03 +03:00
parent 0c5d57346b
commit cd55351042

View File

@ -31,46 +31,30 @@ impl Alpha {
} }
enum AnimPhase { enum AnimPhase {
Shown(i32), Shown,
Hide, Hide,
Hidden(i32), Hidden,
Show, Show,
} }
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 { pub struct State {
alpha: Alpha, alpha: Alpha,
anim_phase: AnimPhase, anim_phase: AnimPhase,
timer: Option<glib::SourceId>,
} }
impl State { impl State {
pub fn new() -> State { pub fn new() -> State {
State { State {
alpha: Alpha(1.0), alpha: Alpha(1.0),
anim_phase: AnimPhase::Shown(500), anim_phase: AnimPhase::Shown,
timer: None,
} }
} }
} }
pub struct Cursor { pub struct Cursor {
timer: Option<glib::SourceId>,
state: Arc<Mutex<State>>, state: Arc<Mutex<State>>,
} }
@ -78,49 +62,16 @@ impl Cursor {
pub fn new() -> Cursor { pub fn new() -> Cursor {
Cursor { Cursor {
timer: None,
state: Arc::new(Mutex::new(State::new())), state: Arc::new(Mutex::new(State::new())),
} }
} }
pub fn start(&mut self) { pub fn start(&mut self) {
if self.timer.is_none() { let state = self.state.clone();
let state = self.state.clone(); let mut mut_state = self.state.lock().unwrap();
self.timer = Some(glib::timeout_add(100, move || { if mut_state.timer.is_none() {
let mut mut_state = state.lock().unwrap(); mut_state.timer = Some(glib::timeout_add(100, move || anim_step(&state)));
// 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 {
AnimPhase::Shown(_) => {
mut_state.anim_phase = AnimPhase::Hide;
}
AnimPhase::Hide => {
if !mut_state.alpha.hide(0.3) {
mut_state.anim_phase = AnimPhase::Hidden(300);
}
}
AnimPhase::Hidden(_) => {
mut_state.anim_phase = AnimPhase::Show;
}
AnimPhase::Show => {
if !mut_state.alpha.show(0.3) {
mut_state.anim_phase = AnimPhase::Shown(500);
}
}
}
SHELL!(&shell = {
let point = shell.model.cur_point();
shell.on_redraw(&RepaintMode::Area(point));
});
glib::Continue(true)
}));
} }
} }
@ -153,9 +104,60 @@ impl Cursor {
} }
} }
// [TODO]: Reset animation phase on events - 2017-03-24 11:33
fn anim_step(state: &Arc<Mutex<State>>) -> glib::Continue {
let moved_state = state.clone();
let mut mut_state = state.lock().unwrap();
let next_event = match mut_state.anim_phase {
AnimPhase::Shown => {
mut_state.anim_phase = AnimPhase::Hide;
Some(100)
}
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;
Some(100)
}
AnimPhase::Show => {
if !mut_state.alpha.show(0.3) {
mut_state.anim_phase = AnimPhase::Shown;
Some(500)
} else {
None
}
}
};
SHELL!(&shell = {
let point = shell.model.cur_point();
shell.on_redraw(&RepaintMode::Area(point));
});
if let Some(timeout) = next_event {
mut_state.timer = Some(glib::timeout_add(timeout, move || anim_step(&moved_state) ));
glib::Continue(false)
} else {
glib::Continue(true)
}
}
impl Drop for Cursor { impl Drop for Cursor {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(timer_id) = self.timer { if let Some(timer_id) = self.state.lock().unwrap().timer {
glib::source_remove(timer_id); glib::source_remove(timer_id);
} }
} }