podcasts/podcasts-gtk/src/stacks/home.rs
Jordan Petridis 9f42e91088
Refactor content state with Application actions
Instead of each view/widget determening if its populated on its own,
make add Application Actions and apply the state globally.
2018-08-19 13:44:11 +03:00

92 lines
2.4 KiB
Rust

use gtk;
use gtk::prelude::*;
use gtk::StackTransitionType;
use crossbeam_channel::Sender;
use failure::Error;
use app::Action;
use stacks::State;
use widgets::{EmptyView, HomeView};
use std::ops::Deref;
use std::rc::Rc;
#[derive(Debug, Clone)]
pub(crate) struct HomeStack {
empty: EmptyView,
episodes: Rc<HomeView>,
stack: gtk::Stack,
state: State,
sender: Sender<Action>,
}
impl HomeStack {
pub(crate) fn new(sender: Sender<Action>) -> Result<HomeStack, Error> {
let episodes = HomeView::new(sender.clone(), None)?;
let empty = EmptyView::default();
let stack = gtk::Stack::new();
let state = State::Empty;
stack.add_named(episodes.view.container(), "home");
stack.add_named(empty.deref(), "empty");
let home = HomeStack {
empty,
episodes,
stack,
state,
sender,
};
Ok(home)
}
pub(crate) fn get_stack(&self) -> gtk::Stack {
self.stack.clone()
}
pub(crate) fn update(&mut self) -> Result<(), Error> {
// Get the container of the view
let old = &self.episodes.view.container().clone();
// Copy the vertical scrollbar adjustment from the old view.
let vadj = self.episodes.view.get_vadjustment();
let eps = HomeView::new(self.sender.clone(), vadj)?;
// Remove the old widget and add the new one
// during this the previous view is removed,
// and the visible child falls back to empty view.
self.stack.remove(old);
self.stack.add_named(eps.view.container(), "home");
// Keep the previous state.
let s = self.state;
// Set the visible child back to the previous one to avoid
// the stack transition animation to show the empty view
self.switch_visible(s, StackTransitionType::None);
// replace view in the struct too
self.episodes = eps;
// This might not be needed
old.destroy();
Ok(())
}
pub(crate) fn switch_visible(&mut self, s: State, animation: StackTransitionType) {
use self::State::*;
match s {
Populated => {
self.stack.set_visible_child_full("home", animation);
self.state = Populated;
}
Empty => {
self.stack.set_visible_child_full("empty", animation);
self.state = Empty;
}
}
}
}