ShowStack: Refactor to make stack restructure easier.

This removes the empty widget from the ShowStack. The plan is
to have a ShowsView which will be the parent of ShowStack and
an Empty Widget. Then make ShowStack have only valid populated
states of ShowsPopulate, ShowWidget and AboutEpisodeWidget later.
This commit is contained in:
Jordan Petridis 2018-04-24 13:12:27 +03:00
parent f173b326a4
commit c4ed90dd5a
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
4 changed files with 52 additions and 57 deletions

View File

@ -10,7 +10,7 @@ use hammond_data::Podcast;
use headerbar::Header; use headerbar::Header;
use settings::{self, WindowGeometry}; use settings::{self, WindowGeometry};
use stacks::Content; use stacks::{Content, ShowState};
use utils; use utils;
use widgets::{mark_all_notif, remove_show_notif}; use widgets::{mark_all_notif, remove_show_notif};
@ -181,11 +181,11 @@ impl App {
} }
Ok(Action::ShowWidgetAnimated) => { Ok(Action::ShowWidgetAnimated) => {
let mut shows = content.get_shows(); let mut shows = content.get_shows();
shows.borrow().switch_widget_animated(); shows.borrow_mut().switch_visible(ShowState::ShowWidget);
} }
Ok(Action::ShowShowsAnimated) => { Ok(Action::ShowShowsAnimated) => {
let mut shows = content.get_shows(); let mut shows = content.get_shows();
shows.borrow().switch_podcasts_animated(); shows.borrow_mut().switch_visible(ShowState::ShowsView);
} }
Ok(Action::HeaderBarShowTile(title)) => headerbar.switch_to_back(&title), Ok(Action::HeaderBarShowTile(title)) => headerbar.switch_to_back(&title),
Ok(Action::HeaderBarNormal) => headerbar.switch_to_normal(), Ok(Action::HeaderBarNormal) => headerbar.switch_to_normal(),

View File

@ -58,7 +58,7 @@ impl Content {
pub fn update_shows_view(&self) { pub fn update_shows_view(&self) {
self.shows self.shows
.borrow_mut() .borrow_mut()
.update_podcasts() .update_shows()
.map_err(|err| error!("Failed to update ShowsView: {}", err)) .map_err(|err| error!("Failed to update ShowsView: {}", err))
.ok(); .ok();
} }

View File

@ -4,4 +4,4 @@ mod show;
pub use self::content::Content; pub use self::content::Content;
pub use self::home::HomeStack; pub use self::home::HomeStack;
pub use self::show::ShowStack; pub use self::show::{ShowStack, ShowState};

View File

@ -4,43 +4,45 @@ use gtk::prelude::*;
use failure::Error; use failure::Error;
use hammond_data::dbqueries; use hammond_data::dbqueries;
use hammond_data::errors::DataError;
use hammond_data::Podcast; use hammond_data::Podcast;
use app::Action; use app::Action;
use widgets::{EmptyView, ShowWidget, ShowsPopulated}; use widgets::{ShowWidget, ShowsPopulated};
use std::rc::Rc; use std::rc::Rc;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::sync::Arc; use std::sync::Arc;
#[derive(Debug, Clone)]
pub enum ShowState {
ShowsView,
ShowWidget,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ShowStack { pub struct ShowStack {
stack: gtk::Stack, populated: Rc<ShowsPopulated>,
podcasts: Rc<ShowsPopulated>,
show: Rc<ShowWidget>, show: Rc<ShowWidget>,
empty: EmptyView, stack: gtk::Stack,
state: ShowState,
sender: Sender<Action>, sender: Sender<Action>,
} }
impl ShowStack { impl ShowStack {
pub fn new(sender: Sender<Action>) -> Result<ShowStack, Error> { pub fn new(sender: Sender<Action>) -> Result<ShowStack, Error> {
let stack = gtk::Stack::new(); let stack = gtk::Stack::new();
let state = ShowState::ShowsView;
let podcasts = ShowsPopulated::new(sender.clone())?; let populated = ShowsPopulated::new(sender.clone())?;
let show = Rc::new(ShowWidget::default()); let show = Rc::new(ShowWidget::default());
let empty = EmptyView::new();
stack.add_named(&podcasts.container, "podcasts"); stack.add_named(&populated.container, "shows");
stack.add_named(&show.container, "widget"); stack.add_named(&show.container, "widget");
stack.add_named(&empty.container, "empty");
set_stack_visible(&stack)?;
let show = ShowStack { let show = ShowStack {
stack, stack,
podcasts, populated,
show, show,
empty, state,
sender, sender,
}; };
@ -52,26 +54,20 @@ impl ShowStack {
// self.update_podcasts(); // self.update_podcasts();
// } // }
pub fn update_podcasts(&mut self) -> Result<(), Error> { pub fn update_shows(&mut self) -> Result<(), Error> {
let vis = self.stack let old = &self.populated.container.clone();
.get_visible_child_name()
.ok_or_else(|| format_err!("Failed to get visible child name."))?;
let old = &self.podcasts.container.clone();
debug!("Name: {:?}", WidgetExt::get_name(old)); debug!("Name: {:?}", WidgetExt::get_name(old));
let pop = ShowsPopulated::new(self.sender.clone())?; let pop = ShowsPopulated::new(self.sender.clone())?;
self.podcasts = pop; self.populated = pop;
self.stack.remove(old); self.stack.remove(old);
self.stack.add_named(&self.podcasts.container, "podcasts"); self.stack.add_named(&self.populated.container, "shows");
if !dbqueries::is_podcasts_populated()? { // The current visible child might change depending on
self.stack.set_visible_child_name("empty"); // removal and insertion in the gtk::Stack, so we have
} else if vis != "empty" { // to make sure it will stay the same.
self.stack.set_visible_child_name(&vis); let s = self.state.clone();
} else { self.switch_visible(s);
self.stack.set_visible_child_name("podcasts");
}
old.destroy(); old.destroy();
Ok(()) Ok(())
@ -104,10 +100,6 @@ impl ShowStack {
} }
pub fn update_widget(&mut self) -> Result<(), Error> { pub fn update_widget(&mut self) -> Result<(), Error> {
let vis = self.stack
.get_visible_child_name()
.ok_or_else(|| format_err!("Failed to get visible child name."))?;
let old = self.show.container.clone(); let old = self.show.container.clone();
let id = WidgetExt::get_name(&old); let id = WidgetExt::get_name(&old);
if id == Some("GtkBox".to_string()) || id.is_none() { if id == Some("GtkBox".to_string()) || id.is_none() {
@ -117,7 +109,13 @@ impl ShowStack {
let id = id.ok_or_else(|| format_err!("Failed to get widget's name."))?; let id = id.ok_or_else(|| format_err!("Failed to get widget's name."))?;
let pd = dbqueries::get_podcast_from_id(id.parse::<i32>()?)?; let pd = dbqueries::get_podcast_from_id(id.parse::<i32>()?)?;
self.replace_widget(Arc::new(pd))?; self.replace_widget(Arc::new(pd))?;
self.stack.set_visible_child_name(&vis);
// The current visible child might change depending on
// removal and insertion in the gtk::Stack, so we have
// to make sure it will stay the same.
let s = self.state.clone();
self.switch_visible(s);
old.destroy(); old.destroy();
Ok(()) Ok(())
} }
@ -134,28 +132,25 @@ impl ShowStack {
self.update_widget() self.update_widget()
} }
pub fn switch_podcasts_animated(&self) {
self.stack
.set_visible_child_full("podcasts", gtk::StackTransitionType::SlideRight);
}
pub fn switch_widget_animated(&self) {
self.stack
.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft)
}
pub fn get_stack(&self) -> gtk::Stack { pub fn get_stack(&self) -> gtk::Stack {
self.stack.clone() self.stack.clone()
} }
}
#[inline] #[inline]
fn set_stack_visible(stack: &gtk::Stack) -> Result<(), DataError> { pub fn switch_visible(&mut self, state: ShowState) {
if dbqueries::is_podcasts_populated()? { use self::ShowState::*;
stack.set_visible_child_name("podcasts")
} else { match state {
stack.set_visible_child_name("empty") ShowsView => {
self.stack
.set_visible_child_full("shows", gtk::StackTransitionType::SlideRight);
self.state = ShowsView;
}
ShowWidget => {
self.stack
.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft);
self.state = ShowWidget;
}
}
} }
Ok(())
} }