163 lines
4.5 KiB
Rust
163 lines
4.5 KiB
Rust
use gtk;
|
|
use gtk::prelude::*;
|
|
use gtk::StackTransitionType;
|
|
|
|
use failure::Error;
|
|
|
|
use hammond_data::dbqueries;
|
|
use hammond_data::Podcast;
|
|
|
|
use app::Action;
|
|
use widgets::{ShowWidget, ShowsView};
|
|
|
|
use std::rc::Rc;
|
|
use std::sync::mpsc::Sender;
|
|
use std::sync::Arc;
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum PopulatedState {
|
|
View,
|
|
Widget,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PopulatedStack {
|
|
container: gtk::Box,
|
|
populated: Rc<ShowsView>,
|
|
show: Rc<ShowWidget>,
|
|
stack: gtk::Stack,
|
|
state: PopulatedState,
|
|
sender: Sender<Action>,
|
|
}
|
|
|
|
impl PopulatedStack {
|
|
pub fn new(sender: Sender<Action>) -> Result<PopulatedStack, Error> {
|
|
let stack = gtk::Stack::new();
|
|
let state = PopulatedState::View;
|
|
let populated = ShowsView::new(sender.clone())?;
|
|
let show = Rc::new(ShowWidget::default());
|
|
let container = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
|
|
|
stack.add_named(&populated.container, "shows");
|
|
stack.add_named(&show.container, "widget");
|
|
container.add(&stack);
|
|
container.show_all();
|
|
|
|
let show = PopulatedStack {
|
|
container,
|
|
stack,
|
|
populated,
|
|
show,
|
|
state,
|
|
sender,
|
|
};
|
|
|
|
Ok(show)
|
|
}
|
|
|
|
pub fn update(&mut self) {
|
|
self.update_widget().map_err(|err| format!("{}", err)).ok();
|
|
self.update_shows().map_err(|err| format!("{}", err)).ok();
|
|
}
|
|
|
|
pub fn update_shows(&mut self) -> Result<(), Error> {
|
|
// 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;
|
|
self.replace_shows()?;
|
|
self.switch_visible(s, StackTransitionType::Crossfade);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn replace_shows(&mut self) -> Result<(), Error> {
|
|
let old = &self.populated.container.clone();
|
|
debug!("Name: {:?}", WidgetExt::get_name(old));
|
|
|
|
self.populated
|
|
.save_alignment()
|
|
.map_err(|err| error!("Failed to set episodes_view allignment: {}", err))
|
|
.ok();
|
|
|
|
let pop = ShowsView::new(self.sender.clone())?;
|
|
self.populated = pop;
|
|
self.stack.remove(old);
|
|
self.stack.add_named(&self.populated.container, "shows");
|
|
|
|
old.destroy();
|
|
Ok(())
|
|
}
|
|
|
|
pub fn replace_widget(&mut self, pd: Arc<Podcast>) -> Result<(), Error> {
|
|
let old = self.show.container.clone();
|
|
|
|
// save the ShowWidget vertical scrollabar alignment
|
|
self.show
|
|
.podcast_id()
|
|
.map(|id| self.show.save_vadjustment(id));
|
|
|
|
let new = ShowWidget::new(pd, self.sender.clone());
|
|
self.show = new;
|
|
self.stack.remove(&old);
|
|
self.stack.add_named(&self.show.container, "widget");
|
|
|
|
// 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;
|
|
self.switch_visible(s, StackTransitionType::None);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn update_widget(&mut self) -> Result<(), Error> {
|
|
let old = self.show.container.clone();
|
|
let id = self.show.podcast_id();
|
|
if id.is_none() {
|
|
return Ok(());
|
|
}
|
|
|
|
let pd = dbqueries::get_podcast_from_id(id.unwrap_or_default())?;
|
|
self.replace_widget(Arc::new(pd))?;
|
|
|
|
// 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;
|
|
self.switch_visible(s, StackTransitionType::Crossfade);
|
|
|
|
old.destroy();
|
|
Ok(())
|
|
}
|
|
|
|
// Only update widget if its podcast_id is equal to pid.
|
|
pub fn update_widget_if_same(&mut self, pid: i32) -> Result<(), Error> {
|
|
if self.show.podcast_id() != Some(pid) {
|
|
debug!("Different widget. Early return");
|
|
return Ok(());
|
|
}
|
|
|
|
self.update_widget()
|
|
}
|
|
|
|
pub fn container(&self) -> gtk::Box {
|
|
self.container.clone()
|
|
}
|
|
|
|
pub fn switch_visible(&mut self, state: PopulatedState, animation: StackTransitionType) {
|
|
use self::PopulatedState::*;
|
|
|
|
match state {
|
|
View => {
|
|
self.stack.set_visible_child_full("shows", animation);
|
|
self.state = View;
|
|
}
|
|
Widget => {
|
|
self.stack.set_visible_child_full("widget", animation);
|
|
self.state = Widget;
|
|
}
|
|
}
|
|
}
|
|
}
|