Probably the worst state machine implementation that was ever written.

This commit is contained in:
Jordan Petridis 2018-02-08 01:50:48 +02:00
parent 45522b86df
commit a96f4c57c9
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6

View File

@ -40,13 +40,100 @@ lazy_static! {
static ref NOW: DateTime<Utc> = Utc::now(); static ref NOW: DateTime<Utc> = Utc::now();
} }
#[derive(Debug, Clone)]
struct Normal;
#[derive(Debug, Clone)]
struct GreyedOut;
#[derive(Debug, Clone)]
struct Title<S> {
title: gtk::Label,
state: S,
}
impl Title<Normal> {
fn new(title: gtk::Label) -> Self {
Title {
title,
state: Normal {},
}
}
fn set_title(&self, s: &str) {
self.title.set_text(s);
}
}
impl Title<GreyedOut> {
fn set_title(&self, s: &str) {
self.title.set_text(s);
}
}
impl From<Title<Normal>> for Title<GreyedOut> {
fn from(machine: Title<Normal>) -> Self {
machine
.title
.get_style_context()
.map(|c| c.add_class("dim-label"));
Title {
title: machine.title,
state: GreyedOut {},
}
}
}
impl From<Title<GreyedOut>> for Title<Normal> {
fn from(machine: Title<GreyedOut>) -> Self {
machine
.title
.get_style_context()
.map(|c| c.remove_class("dim-label"));
Title {
title: machine.title,
state: Normal {},
}
}
}
#[derive(Debug, Clone)]
enum TitleMachine {
Normal(Title<Normal>),
GreyedOut(Title<GreyedOut>),
}
impl TitleMachine {
fn new(label: gtk::Label, is_played: bool) -> Self {
let m = TitleMachine::Normal(Title::<Normal>::new(label));
m.determine_state(is_played)
}
fn determine_state(self, is_played: bool) -> Self {
match (self, is_played) {
(title @ TitleMachine::Normal(_), false) => title,
(title @ TitleMachine::GreyedOut(_), true) => title,
(TitleMachine::Normal(val), true) => TitleMachine::GreyedOut(val.into()),
(TitleMachine::GreyedOut(val), false) => TitleMachine::Normal(val.into()),
}
}
fn set_title(&self, s: &str) {
match *self {
TitleMachine::Normal(ref val) => val.set_title(s),
TitleMachine::GreyedOut(ref val) => val.set_title(s),
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EpisodeWidget { pub struct EpisodeWidget {
pub container: gtk::Box, pub container: gtk::Box,
play: gtk::Button, play: gtk::Button,
download: gtk::Button, download: gtk::Button,
cancel: gtk::Button, cancel: gtk::Button,
title: gtk::Label, title: TitleMachine,
date: gtk::Label, date: gtk::Label,
duration: gtk::Label, duration: gtk::Label,
progress: gtk::ProgressBar, progress: gtk::ProgressBar,
@ -78,13 +165,15 @@ impl Default for EpisodeWidget {
let separator2: gtk::Label = builder.get_object("separator2").unwrap(); let separator2: gtk::Label = builder.get_object("separator2").unwrap();
let prog_separator: gtk::Label = builder.get_object("prog_separator").unwrap(); let prog_separator: gtk::Label = builder.get_object("prog_separator").unwrap();
let title_machine = TitleMachine::new(title, false);
EpisodeWidget { EpisodeWidget {
container, container,
progress, progress,
download, download,
play, play,
cancel, cancel,
title, title: title_machine,
duration, duration,
date, date,
total_size, total_size,
@ -98,16 +187,15 @@ impl Default for EpisodeWidget {
impl EpisodeWidget { impl EpisodeWidget {
pub fn new(episode: EpisodeWidgetQuery, sender: Sender<Action>) -> EpisodeWidget { pub fn new(episode: EpisodeWidgetQuery, sender: Sender<Action>) -> EpisodeWidget {
let widget = EpisodeWidget::default(); let mut widget = EpisodeWidget::default();
widget.init(episode, sender); widget.init(episode, sender)
widget
} }
fn init(&self, episode: EpisodeWidgetQuery, sender: Sender<Action>) { fn init(mut self, episode: EpisodeWidgetQuery, sender: Sender<Action>) -> Self {
WidgetExt::set_name(&self.container, &episode.rowid().to_string()); WidgetExt::set_name(&self.container, &episode.rowid().to_string());
// Set the title label state. // Set the title label state.
self.set_title(&episode); self = self.set_title(&episode);
// Set the duaration label. // Set the duaration label.
self.set_duration(episode.duration()); self.set_duration(episode.duration());
@ -135,15 +223,15 @@ impl EpisodeWidget {
let episode = Arc::new(Mutex::new(episode)); let episode = Arc::new(Mutex::new(episode));
let title = self.title.clone(); // let title = self.title.clone();
self.play // self.play
.connect_clicked(clone!(episode, sender => move |_| { // .connect_clicked(clone!(episode, sender => move |_| {
if let Ok(mut ep) = episode.lock() { // if let Ok(mut ep) = episode.lock() {
if let Err(err) = on_play_bttn_clicked(&mut ep, &title, sender.clone()){ // if let Err(err) = on_play_bttn_clicked(&mut ep, &title, sender.clone()){
error!("Error: {}", err); // error!("Error: {}", err);
}; // };
} // }
})); // }));
self.download self.download
.connect_clicked(clone!(episode, sender => move |dl| { .connect_clicked(clone!(episode, sender => move |dl| {
@ -157,6 +245,8 @@ impl EpisodeWidget {
} }
} }
})); }));
self
} }
/// Show or hide the play/delete/download buttons upon widget initialization. /// Show or hide the play/delete/download buttons upon widget initialization.
@ -170,15 +260,10 @@ impl EpisodeWidget {
} }
/// Determine the title state. /// Determine the title state.
fn set_title(&self, episode: &EpisodeWidgetQuery) { fn set_title(mut self, episode: &EpisodeWidgetQuery) -> Self {
self.title.set_text(episode.title()); self.title.set_title(episode.title());
self.title = self.title.determine_state(episode.played().is_some());
// Grey out the title if the episode is played. self
if episode.played().is_some() {
self.title
.get_style_context()
.map(|c| c.add_class("dim-label"));
}
} }
/// Set the date label depending on the current time. /// Set the date label depending on the current time.