diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs index 169ac24..d464acb 100644 --- a/hammond-gtk/src/app.rs +++ b/hammond-gtk/src/app.rs @@ -6,8 +6,8 @@ use gtk::prelude::*; use hammond_data::{Podcast, Source}; use hammond_data::utils::checkup; -use content::Content; use headerbar::Header; +use stacks::Content; use utils; use std::sync::Arc; diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index 399d3c6..2f01793 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use std::sync::mpsc::Sender; use app::Action; -use content::Content; +use stacks::Content; #[derive(Debug, Clone)] pub struct Header { diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index eb66a6a..6e04e6e 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -53,8 +53,9 @@ macro_rules! clone { mod views; mod widgets; +mod stacks; + mod headerbar; -mod content; mod app; mod utils; diff --git a/hammond-gtk/src/stacks/content.rs b/hammond-gtk/src/stacks/content.rs new file mode 100644 index 0000000..d2923b5 --- /dev/null +++ b/hammond-gtk/src/stacks/content.rs @@ -0,0 +1,94 @@ +use gtk; +use gtk::prelude::*; + +use failure::Error; + +use app::Action; +use stacks::EpisodeStack; +use stacks::ShowStack; + +use std::sync::Arc; +use std::sync::mpsc::Sender; + +#[derive(Debug, Clone)] +pub struct Content { + stack: gtk::Stack, + shows: Arc, + episodes: Arc, + sender: Sender, +} + +impl Content { + pub fn new(sender: Sender) -> Result { + let stack = gtk::Stack::new(); + let episodes = Arc::new(EpisodeStack::new(sender.clone())?); + let shows = Arc::new(ShowStack::new(sender.clone())?); + + stack.add_titled(&episodes.stack, "episodes", "Episodes"); + stack.add_titled(&shows.stack, "shows", "Shows"); + + Ok(Content { + stack, + shows, + episodes, + sender, + }) + } + + pub fn update(&self) { + self.update_episode_view(); + self.update_shows_view(); + self.update_widget() + } + + // TODO: Maybe propagate the error? + pub fn update_episode_view(&self) { + if let Err(err) = self.episodes.update() { + error!("Something went wrong while trying to update the episode view."); + error!("Error: {}", err); + } + } + + pub fn update_episode_view_if_baground(&self) { + if self.stack.get_visible_child_name() != Some("episodes".into()) { + self.update_episode_view(); + } + } + + pub fn update_shows_view(&self) { + if let Err(err) = self.shows.update_podcasts() { + error!("Something went wrong while trying to update the ShowsView."); + error!("Error: {}", err); + } + } + + pub fn update_widget(&self) { + if let Err(err) = self.shows.update_widget() { + error!("Something went wrong while trying to update the Show Widget."); + error!("Error: {}", err); + } + } + + pub fn update_widget_if_same(&self, pid: i32) { + if let Err(err) = self.shows.update_widget_if_same(pid) { + error!("Something went wrong while trying to update the Show Widget."); + error!("Error: {}", err); + } + } + + pub fn update_widget_if_visible(&self) { + if self.stack.get_visible_child_name() == Some("shows".to_string()) + && self.shows.get_stack().get_visible_child_name() == Some("widget".to_string()) + { + self.update_widget(); + } + } + + pub fn get_stack(&self) -> gtk::Stack { + self.stack.clone() + } + + pub fn get_shows(&self) -> Arc { + self.shows.clone() + } +} diff --git a/hammond-gtk/src/stacks/episode.rs b/hammond-gtk/src/stacks/episode.rs new file mode 100644 index 0000000..bddd328 --- /dev/null +++ b/hammond-gtk/src/stacks/episode.rs @@ -0,0 +1,75 @@ +use gtk; +use gtk::Cast; +use gtk::prelude::*; + +use failure::Error; + +use views::empty::EmptyView; +use views::episodes::EpisodesView; + +use app::Action; + +use std::sync::mpsc::Sender; + +#[derive(Debug, Clone)] +pub struct EpisodeStack { + // FIXME: remove pub + pub stack: gtk::Stack, + sender: Sender, +} + +impl EpisodeStack { + pub fn new(sender: Sender) -> Result { + let episodes = EpisodesView::new(sender.clone())?; + let empty = EmptyView::new(); + let stack = gtk::Stack::new(); + + stack.add_named(&episodes.container, "episodes"); + stack.add_named(&empty.container, "empty"); + + if episodes.is_empty() { + stack.set_visible_child_name("empty"); + } else { + stack.set_visible_child_name("episodes"); + } + + Ok(EpisodeStack { stack, sender }) + } + + // Look into refactoring to a state-machine. + pub fn update(&self) -> Result<(), Error> { + let old = self.stack + .get_child_by_name("episodes") + .ok_or_else(|| format_err!("Faild to get \"episodes\" child from the stack."))? + .downcast::() + .map_err(|_| format_err!("Failed to downcast stack child to a Box."))?; + debug!("Name: {:?}", WidgetExt::get_name(&old)); + + let scrolled_window = old.get_children() + .first() + .ok_or_else(|| format_err!("Box container has no childs."))? + .clone() + .downcast::() + .map_err(|_| format_err!("Failed to downcast stack child to a ScrolledWindow."))?; + debug!("Name: {:?}", WidgetExt::get_name(&scrolled_window)); + + let eps = EpisodesView::new(self.sender.clone())?; + // Copy the vertical scrollbar adjustment from the old view into the new one. + scrolled_window + .get_vadjustment() + .map(|x| eps.set_vadjustment(&x)); + + self.stack.remove(&old); + self.stack.add_named(&eps.container, "episodes"); + + if eps.is_empty() { + self.stack.set_visible_child_name("empty"); + } else { + self.stack.set_visible_child_name("episodes"); + } + + old.destroy(); + + Ok(()) + } +} diff --git a/hammond-gtk/src/stacks/mod.rs b/hammond-gtk/src/stacks/mod.rs new file mode 100644 index 0000000..e038f99 --- /dev/null +++ b/hammond-gtk/src/stacks/mod.rs @@ -0,0 +1,7 @@ +mod content; +mod episode; +mod show; + +pub use self::content::Content; +pub use self::episode::EpisodeStack; +pub use self::show::ShowStack; diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/stacks/show.rs similarity index 56% rename from hammond-gtk/src/content.rs rename to hammond-gtk/src/stacks/show.rs index f73803c..287f86d 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/stacks/show.rs @@ -8,106 +8,22 @@ use hammond_data::Podcast; use hammond_data::dbqueries; use views::empty::EmptyView; -use views::episodes::EpisodesView; use views::shows::ShowsPopulated; use app::Action; use widgets::show::ShowWidget; -use std::sync::Arc; use std::sync::mpsc::Sender; -#[derive(Debug, Clone)] -pub struct Content { - stack: gtk::Stack, - shows: Arc, - episodes: Arc, - sender: Sender, -} - -impl Content { - pub fn new(sender: Sender) -> Result { - let stack = gtk::Stack::new(); - let episodes = Arc::new(EpisodeStack::new(sender.clone())?); - let shows = Arc::new(ShowStack::new(sender.clone())?); - - stack.add_titled(&episodes.stack, "episodes", "Episodes"); - stack.add_titled(&shows.stack, "shows", "Shows"); - - Ok(Content { - stack, - shows, - episodes, - sender, - }) - } - - pub fn update(&self) { - self.update_episode_view(); - self.update_shows_view(); - self.update_widget() - } - - // TODO: Maybe propagate the error? - pub fn update_episode_view(&self) { - if let Err(err) = self.episodes.update() { - error!("Something went wrong while trying to update the episode view."); - error!("Error: {}", err); - } - } - - pub fn update_episode_view_if_baground(&self) { - if self.stack.get_visible_child_name() != Some("episodes".into()) { - self.update_episode_view(); - } - } - - pub fn update_shows_view(&self) { - if let Err(err) = self.shows.update_podcasts() { - error!("Something went wrong while trying to update the ShowsView."); - error!("Error: {}", err); - } - } - - pub fn update_widget(&self) { - if let Err(err) = self.shows.update_widget() { - error!("Something went wrong while trying to update the Show Widget."); - error!("Error: {}", err); - } - } - - pub fn update_widget_if_same(&self, pid: i32) { - if let Err(err) = self.shows.update_widget_if_same(pid) { - error!("Something went wrong while trying to update the Show Widget."); - error!("Error: {}", err); - } - } - - pub fn update_widget_if_visible(&self) { - if self.stack.get_visible_child_name() == Some("shows".to_string()) - && self.shows.get_stack().get_visible_child_name() == Some("widget".to_string()) - { - self.update_widget(); - } - } - - pub fn get_stack(&self) -> gtk::Stack { - self.stack.clone() - } - - pub fn get_shows(&self) -> Arc { - self.shows.clone() - } -} - #[derive(Debug, Clone)] pub struct ShowStack { - stack: gtk::Stack, + // FIXME: remove pub + pub stack: gtk::Stack, sender: Sender, } impl ShowStack { - fn new(sender: Sender) -> Result { + pub fn new(sender: Sender) -> Result { let stack = gtk::Stack::new(); let show = ShowStack { @@ -263,65 +179,3 @@ impl ShowStack { self.stack.clone() } } - -#[derive(Debug, Clone)] -pub struct EpisodeStack { - stack: gtk::Stack, - sender: Sender, -} - -impl EpisodeStack { - fn new(sender: Sender) -> Result { - let episodes = EpisodesView::new(sender.clone())?; - let empty = EmptyView::new(); - let stack = gtk::Stack::new(); - - stack.add_named(&episodes.container, "episodes"); - stack.add_named(&empty.container, "empty"); - - if episodes.is_empty() { - stack.set_visible_child_name("empty"); - } else { - stack.set_visible_child_name("episodes"); - } - - Ok(EpisodeStack { stack, sender }) - } - - // Look into refactoring to a state-machine. - pub fn update(&self) -> Result<(), Error> { - let old = self.stack - .get_child_by_name("episodes") - .ok_or_else(|| format_err!("Faild to get \"episodes\" child from the stack."))? - .downcast::() - .map_err(|_| format_err!("Failed to downcast stack child to a Box."))?; - debug!("Name: {:?}", WidgetExt::get_name(&old)); - - let scrolled_window = old.get_children() - .first() - .ok_or_else(|| format_err!("Box container has no childs."))? - .clone() - .downcast::() - .map_err(|_| format_err!("Failed to downcast stack child to a ScrolledWindow."))?; - debug!("Name: {:?}", WidgetExt::get_name(&scrolled_window)); - - let eps = EpisodesView::new(self.sender.clone())?; - // Copy the vertical scrollbar adjustment from the old view into the new one. - scrolled_window - .get_vadjustment() - .map(|x| eps.set_vadjustment(&x)); - - self.stack.remove(&old); - self.stack.add_named(&eps.container, "episodes"); - - if eps.is_empty() { - self.stack.set_visible_child_name("empty"); - } else { - self.stack.set_visible_child_name("episodes"); - } - - old.destroy(); - - Ok(()) - } -}