use gtk; use gtk::prelude::*; use hammond_data::Podcast; use hammond_data::dbqueries; use widgets::podcast::PodcastWidget; use views::podcasts::PopulatedView; use views::empty::EmptyView; pub struct Content { pub stack: gtk::Stack, shows: ShowStateWrapper, episodes: EpisodeStateWrapper, } impl Content { pub fn new() -> Content { let stack = gtk::Stack::new(); let shows = ShowStateWrapper::new(); let episodes = EpisodeStateWrapper::new(); let shows_stack = shows.get_stack(); let ep_stack = episodes.get_stack(); stack.add_titled(&ep_stack, "episodes", "Episodes"); stack.add_titled(&shows_stack, "shows", "Shows"); Content { stack, shows, episodes, } } pub fn update(&mut self) { self.shows.update(); self.episodes.update(); } } fn replace_widget(stack: >k::Stack, pdw: &PodcastWidget) { let old = stack.get_child_by_name("widget").unwrap(); stack.remove(&old); stack.add_titled(&pdw.container, "widget", "Episode"); old.destroy(); } fn replace_podcasts(stack: >k::Stack, pop: &PopulatedView) { let old = stack.get_child_by_name("podcasts").unwrap(); stack.remove(&old); stack.add_titled(&pop.container, "podcasts", "Shows"); old.destroy(); } pub fn update_podcasts(stack: >k::Stack) { let pods = PopulatedView::new_initialized(); replace_podcasts(stack, &pods); } pub fn update_widget(stack: >k::Stack, pd: &Podcast) { let pdw = PodcastWidget::new_initialized(stack, pd); replace_widget(stack, &pdw); } pub fn update_podcasts_preserve_vis(stack: >k::Stack) { let vis = stack.get_visible_child_name().unwrap(); update_podcasts(stack); if vis != "empty" { stack.set_visible_child_name(&vis) } } pub fn update_widget_preserve_vis(stack: >k::Stack, pd: &Podcast) { let vis = stack.get_visible_child_name().unwrap(); update_widget(stack, pd); stack.set_visible_child_name(&vis) } // pub fn on_podcasts_child_activate(stack: >k::Stack, pd: &Podcast) { // update_widget(stack, pd); // stack.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft); // } // FIXME: Rename and remove aliases type ShowsPopulated = PopulatedView; type ShowsEmpty = EmptyView; type EpisodesPopulated = PodcastWidget; type EpisodesEmpty = EmptyView; struct Populated; struct Empty; // struct Shows; // struct Episodes; // Thats probably too overengineered // struct StackStateMachine { // shows: ShowsMachine, // episodes: EpisodesMachine, // stack: gtk::Stack, // state: T, // } #[derive(Debug, Clone)] struct ShowsMachine { populated: ShowsPopulated, empty: ShowsEmpty, stack: gtk::Stack, state: S, } impl ShowsMachine { fn update(&mut self) { let vis = self.stack.get_visible_child_name().unwrap(); let old = self.stack.get_child_by_name("populated").unwrap(); self.stack.remove(&old); let pop = ShowsPopulated::new_initialized(); self.populated = pop; self.stack.add_named(&self.populated.container, "populated"); self.stack.set_visible_child_name(&vis); } } #[derive(Debug)] struct EpisodesMachine { populated: EpisodesPopulated, empty: EpisodesEmpty, stack: gtk::Stack, state: S, } impl EpisodesMachine { // FIXME: fn update(&mut self) { let vis = self.stack.get_visible_child_name().unwrap(); let old = self.stack.get_child_by_name("populated").unwrap(); let id = WidgetExt::get_name(&old).unwrap(); if id == "GtkBox" { return; } let pd = dbqueries::get_podcast_from_id(id.parse::().unwrap()).unwrap(); let pdw = EpisodesPopulated::new_initialized(&self.stack, &pd); self.populated = pdw; self.stack.remove(&old); self.stack.add_named(&self.populated.container, "populated"); self.stack.set_visible_child_name(&vis); } } // impl Into> for StackStateMachine { // fn into(self) -> StackStateMachine { // self.stack.set_visible_child_name("shows"); // StackStateMachine { // shows: self.shows, // episodes: self.episodes, // stack: self.stack, // state: Shows {}, // } // } // } // impl Into> for StackStateMachine { // fn into(self) -> StackStateMachine { // self.stack.set_visible_child_name("episodes"); // StackStateMachine { // shows: self.shows, // episodes: self.episodes, // stack: self.stack, // state: Episodes {}, // } // } // } // TODO: Impl instead of impl Into> for ShowsMachine { fn into(self) -> ShowsMachine { self.stack.set_visible_child_name("populated"); ShowsMachine { populated: self.populated, empty: self.empty, stack: self.stack, state: Populated {}, } } } impl Into> for ShowsMachine { fn into(self) -> ShowsMachine { self.stack.set_visible_child_name("empty"); ShowsMachine { populated: self.populated, empty: self.empty, stack: self.stack, state: Empty {}, } } } impl Into> for EpisodesMachine { fn into(self) -> EpisodesMachine { self.stack.set_visible_child_name("populated"); EpisodesMachine { populated: self.populated, empty: self.empty, stack: self.stack, state: Populated {}, } } } impl Into> for EpisodesMachine { fn into(self) -> EpisodesMachine { self.stack.set_visible_child_name("empty"); EpisodesMachine { populated: self.populated, empty: self.empty, stack: self.stack, state: Empty {}, } } } // enum StackStateWrapper { // Shows(StackStateMachine), // Episodes(StackStateMachine), // } enum ShowStateWrapper { Populated(ShowsMachine), Empty(ShowsMachine), } enum EpisodeStateWrapper { Populated(EpisodesMachine), Empty(EpisodesMachine), } // impl StackStateWrapper { // fn switch(mut self) -> Self { // match self { // StackStateWrapper::Shows(val) => StackStateWrapper::Episodes(val.into()), // StackStateWrapper::Episodes(val) => StackStateWrapper::Shows(val.into()) // } // } // } impl ShowStateWrapper { fn new() -> Self { let stack = gtk::Stack::new(); let pop = ShowsPopulated::new_initialized(); let empty = EmptyView::new(); stack.add_named(&pop.container, "populated"); stack.add_named(&empty.container, "empty"); if pop.flowbox.get_children().is_empty() { stack.set_visible_child_name("empty"); ShowStateWrapper::Empty(ShowsMachine { empty, populated: pop, stack, state: Empty {}, }) } else { stack.set_visible_child_name("populated"); ShowStateWrapper::Populated(ShowsMachine { empty, populated: pop, stack, state: Populated {}, }) } } fn switch(self) -> Self { match self { ShowStateWrapper::Populated(val) => ShowStateWrapper::Empty(val.into()), ShowStateWrapper::Empty(val) => ShowStateWrapper::Populated(val.into()), } } fn update(&mut self) { match *self { ShowStateWrapper::Populated(ref mut val) => val.update(), ShowStateWrapper::Empty(ref mut val) => val.update(), } } fn get_stack(&self) -> gtk::Stack { match *self { ShowStateWrapper::Populated(ref val) => val.stack.clone(), ShowStateWrapper::Empty(ref val) => val.stack.clone(), } } } impl EpisodeStateWrapper { // FIXME: fn new() -> Self { let pop = PodcastWidget::new(); let empty = EmptyView::new(); let stack = gtk::Stack::new(); stack.add_named(&pop.container, "populated"); stack.add_named(&empty.container, "empty"); stack.set_visible_child_name("empty"); EpisodeStateWrapper::Empty(EpisodesMachine { empty, populated: pop, stack, state: Empty {}, }) } fn update(&mut self) { match *self { EpisodeStateWrapper::Populated(ref mut val) => val.update(), EpisodeStateWrapper::Empty(ref mut val) => val.update(), } } fn switch(self) -> Self { match self { EpisodeStateWrapper::Populated(val) => EpisodeStateWrapper::Empty(val.into()), EpisodeStateWrapper::Empty(val) => EpisodeStateWrapper::Populated(val.into()), } } fn get_stack(&self) -> gtk::Stack { match *self { EpisodeStateWrapper::Populated(ref val) => val.stack.clone(), EpisodeStateWrapper::Empty(ref val) => val.stack.clone(), } } }