Migrate Headerbar transitions into Channel actions.

This commit is contained in:
Jordan Petridis 2018-01-03 08:02:06 +02:00
parent 2633161c67
commit c33b493dcd
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
5 changed files with 35 additions and 91 deletions

View File

@ -20,6 +20,8 @@ pub enum Action {
UpdateSources(Option<Source>), UpdateSources(Option<Source>),
RefreshViews, RefreshViews,
RefreshEpisodesViewBGR, RefreshEpisodesViewBGR,
HeaderBarShowTile(String),
HeaderBarNormal,
} }
#[derive(Debug)] #[derive(Debug)]
@ -53,16 +55,11 @@ impl App {
let (sender, receiver) = channel(); let (sender, receiver) = channel();
// TODO: Refactor the initialization order. // Create a content instance
let content = Content::new(sender.clone());
// Create the headerbar // Create the headerbar
let header = Rc::new(Header::default()); let header = Header::new(content.clone(), sender);
// Create a content instance
let content = Content::new(header.clone(), sender.clone());
// Initialize the headerbar
header.init(content.clone(), sender.clone());
// Add the Headerbar to the window. // Add the Headerbar to the window.
window.set_titlebar(&header.container); window.set_titlebar(&header.container);
@ -146,6 +143,12 @@ impl App {
Ok(Action::RefreshEpisodesViewBGR) => { Ok(Action::RefreshEpisodesViewBGR) => {
content.update_episode_view_if_baground(); content.update_episode_view_if_baground();
} }
Ok(Action::HeaderBarShowTile(title)) => {
headerbar.switch_to_back(&title)
}
Ok(Action::HeaderBarNormal) => {
headerbar.switch_to_normal()
}
_ => (), _ => (),
} }

View File

@ -9,7 +9,6 @@ use views::empty::EmptyView;
use views::episodes::EpisodesView; use views::episodes::EpisodesView;
use widgets::show::ShowWidget; use widgets::show::ShowWidget;
use headerbar::Header;
use app::Action; use app::Action;
use std::rc::Rc; use std::rc::Rc;
@ -24,10 +23,10 @@ pub struct Content {
} }
impl Content { impl Content {
pub fn new(header: Rc<Header>, sender: Sender<Action>) -> Rc<Content> { pub fn new(sender: Sender<Action>) -> Rc<Content> {
let stack = gtk::Stack::new(); let stack = gtk::Stack::new();
let episodes = EpisodeStack::new(sender.clone()); let episodes = EpisodeStack::new(sender.clone());
let shows = ShowStack::new(header, episodes.clone(), sender.clone()); let shows = ShowStack::new(episodes.clone(), sender.clone());
stack.add_titled(&episodes.stack, "episodes", "Episodes"); stack.add_titled(&episodes.stack, "episodes", "Episodes");
stack.add_titled(&shows.stack, "shows", "Shows"); stack.add_titled(&shows.stack, "shows", "Shows");
@ -71,23 +70,21 @@ impl Content {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ShowStack { pub struct ShowStack {
stack: gtk::Stack, stack: gtk::Stack,
header: Rc<Header>,
epstack: Rc<EpisodeStack>, epstack: Rc<EpisodeStack>,
sender: Sender<Action>, sender: Sender<Action>,
} }
impl ShowStack { impl ShowStack {
fn new(header: Rc<Header>, epstack: Rc<EpisodeStack>, sender: Sender<Action>) -> Rc<ShowStack> { fn new(epstack: Rc<EpisodeStack>, sender: Sender<Action>) -> Rc<ShowStack> {
let stack = gtk::Stack::new(); let stack = gtk::Stack::new();
let show = Rc::new(ShowStack { let show = Rc::new(ShowStack {
stack, stack,
header: header.clone(),
epstack, epstack,
sender, sender: sender.clone(),
}); });
let pop = ShowsPopulated::new(show.clone(), header); let pop = ShowsPopulated::new(show.clone(), sender.clone());
let widget = ShowWidget::default(); let widget = ShowWidget::default();
let empty = EmptyView::new(); let empty = EmptyView::new();
@ -118,7 +115,7 @@ impl ShowStack {
let old = self.stack.get_child_by_name("podcasts").unwrap(); let old = self.stack.get_child_by_name("podcasts").unwrap();
let pop = ShowsPopulated::default(); let pop = ShowsPopulated::default();
pop.init(Rc::new(self.clone()), self.header.clone()); pop.init(Rc::new(self.clone()), self.sender.clone());
self.stack.remove(&old); self.stack.remove(&old);
self.stack.add_named(&pop.container, "podcasts"); self.stack.add_named(&pop.container, "podcasts");
@ -136,12 +133,7 @@ impl ShowStack {
pub fn replace_widget(&self, pd: &Podcast) { pub fn replace_widget(&self, pd: &Podcast) {
let old = self.stack.get_child_by_name("widget").unwrap(); let old = self.stack.get_child_by_name("widget").unwrap();
let new = ShowWidget::new( let new = ShowWidget::new(Rc::new(self.clone()), pd, self.sender.clone());
Rc::new(self.clone()),
self.header.clone(),
pd,
self.sender.clone(),
);
self.stack.remove(&old); self.stack.remove(&old);
self.stack.add_named(&new.container, "widget"); self.stack.add_named(&new.container, "widget");

View File

@ -7,9 +7,10 @@ use hammond_data::Podcast;
use utils::get_pixbuf_from_path; use utils::get_pixbuf_from_path;
use content::ShowStack; use content::ShowStack;
use headerbar::Header; use app::Action;
use std::rc::Rc; use std::rc::Rc;
use std::sync::mpsc::Sender;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ShowsPopulated { pub struct ShowsPopulated {
@ -34,24 +35,24 @@ impl Default for ShowsPopulated {
} }
impl ShowsPopulated { impl ShowsPopulated {
pub fn new(show: Rc<ShowStack>, header: Rc<Header>) -> ShowsPopulated { pub fn new(show: Rc<ShowStack>, sender: Sender<Action>) -> ShowsPopulated {
let pop = ShowsPopulated::default(); let pop = ShowsPopulated::default();
pop.init(show, header); pop.init(show, sender);
pop pop
} }
pub fn init(&self, show: Rc<ShowStack>, header: Rc<Header>) { pub fn init(&self, show: Rc<ShowStack>, sender: Sender<Action>) {
use gtk::WidgetExt; use gtk::WidgetExt;
// TODO: handle unwraps. // TODO: handle unwraps.
self.flowbox self.flowbox
.connect_child_activated(clone!(show => move |_, child| { .connect_child_activated(clone!(show, sender => move |_, child| {
// This is such an ugly hack... // This is such an ugly hack...
let id = WidgetExt::get_name(child).unwrap().parse::<i32>().unwrap(); let id = WidgetExt::get_name(child).unwrap().parse::<i32>().unwrap();
let pd = dbqueries::get_podcast_from_id(id).unwrap(); let pd = dbqueries::get_podcast_from_id(id).unwrap();
show.replace_widget(&pd); show.replace_widget(&pd);
header.switch_to_back(pd.title()); sender.send(Action::HeaderBarShowTile(pd.title().into())).unwrap();
show.switch_widget_animated(); show.switch_widget_animated();
})); }));
// Populate the flowbox with the Podcasts. // Populate the flowbox with the Podcasts.

View File

@ -16,24 +16,9 @@ use hammond_downloader::downloader;
use app::Action; use app::Action;
use std::thread; use std::thread;
use std::cell::RefCell; use std::sync::mpsc::Sender;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::path::Path; use std::path::Path;
type Foo = RefCell<
Option<
(
gtk::Button,
gtk::Button,
gtk::Button,
gtk::ProgressBar,
Receiver<bool>,
),
>,
>;
thread_local!(static GLOBAL: Foo = RefCell::new(None));
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EpisodeWidget { pub struct EpisodeWidget {
pub container: gtk::Box, pub container: gtk::Box,
@ -126,21 +111,18 @@ impl EpisodeWidget {
}; };
})); }));
let play = &self.play;
let cancel = &self.cancel; let cancel = &self.cancel;
let progress = self.progress.clone(); let progress = self.progress.clone();
self.download.connect_clicked( self.download
clone!(play, episode, cancel, progress, sender => move |dl| { .connect_clicked(clone!(episode, cancel, progress, sender => move |dl| {
on_download_clicked( on_download_clicked(
&mut episode.clone(), &mut episode.clone(),
dl, dl,
&play,
&cancel, &cancel,
progress.clone(), progress.clone(),
sender.clone() sender.clone()
); );
}), }));
);
} }
/// Show or hide the play/delete/download buttons upon widget initialization. /// Show or hide the play/delete/download buttons upon widget initialization.
@ -216,7 +198,6 @@ impl EpisodeWidget {
fn on_download_clicked( fn on_download_clicked(
ep: &mut EpisodeWidgetQuery, ep: &mut EpisodeWidgetQuery,
download_bttn: &gtk::Button, download_bttn: &gtk::Button,
play_bttn: &gtk::Button,
cancel_bttn: &gtk::Button, cancel_bttn: &gtk::Button,
progress_bar: gtk::ProgressBar, progress_bar: gtk::ProgressBar,
sender: Sender<Action>, sender: Sender<Action>,
@ -235,7 +216,7 @@ fn on_download_clicked(
cancel_bttn.show(); cancel_bttn.show();
progress.show(); progress.show();
download_bttn.hide(); download_bttn.hide();
sender.send(Action::RefreshEpisodesViewBGR); sender.send(Action::RefreshEpisodesViewBGR).unwrap();
thread::spawn(move || { thread::spawn(move || {
let download_fold = downloader::get_download_folder(&pd_title).unwrap(); let download_fold = downloader::get_download_folder(&pd_title).unwrap();
let e = downloader::get_episode(&mut ep, download_fold.as_str()); let e = downloader::get_episode(&mut ep, download_fold.as_str());
@ -243,7 +224,7 @@ fn on_download_clicked(
error!("Error while trying to download: {:?}", ep.uri()); error!("Error while trying to download: {:?}", ep.uri());
error!("Error: {}", err); error!("Error: {}", err);
}; };
sender.send(Action::RefreshViews); sender.send(Action::RefreshViews).unwrap();
}); });
} }
@ -279,27 +260,6 @@ fn on_play_bttn_clicked(episode_id: i32) {
// }; // };
// } // }
fn receive() -> glib::Continue {
GLOBAL.with(|global| {
if let Some((
ref download_bttn,
ref play_bttn,
ref cancel_bttn,
ref progress_bar,
ref reciever,
)) = *global.borrow()
{
if reciever.try_recv().is_ok() {
download_bttn.hide();
play_bttn.show();
cancel_bttn.hide();
progress_bar.hide();
}
}
});
glib::Continue(false)
}
pub fn episodes_listbox(pd: &Podcast, sender: Sender<Action>) -> Result<gtk::ListBox> { pub fn episodes_listbox(pd: &Podcast, sender: Sender<Action>) -> Result<gtk::ListBox> {
let episodes = dbqueries::get_pd_episodeswidgets(pd)?; let episodes = dbqueries::get_pd_episodeswidgets(pd)?;

View File

@ -12,7 +12,6 @@ use hammond_downloader::downloader;
use widgets::episode::episodes_listbox; use widgets::episode::episodes_listbox;
use utils::get_pixbuf_from_path; use utils::get_pixbuf_from_path;
use content::ShowStack; use content::ShowStack;
use headerbar::Header;
use app::Action; use app::Action;
use std::rc::Rc; use std::rc::Rc;
@ -55,31 +54,20 @@ impl Default for ShowWidget {
} }
impl ShowWidget { impl ShowWidget {
pub fn new( pub fn new(shows: Rc<ShowStack>, pd: &Podcast, sender: Sender<Action>) -> ShowWidget {
shows: Rc<ShowStack>,
header: Rc<Header>,
pd: &Podcast,
sender: Sender<Action>,
) -> ShowWidget {
let pdw = ShowWidget::default(); let pdw = ShowWidget::default();
pdw.init(shows, header, pd, sender); pdw.init(shows, pd, sender);
pdw pdw
} }
pub fn init( pub fn init(&self, shows: Rc<ShowStack>, pd: &Podcast, sender: Sender<Action>) {
&self,
shows: Rc<ShowStack>,
header: Rc<Header>,
pd: &Podcast,
sender: Sender<Action>,
) {
// Hacky workaround so the pd.id() can be retrieved from the `ShowStack`. // Hacky workaround so the pd.id() can be retrieved from the `ShowStack`.
WidgetExt::set_name(&self.container, &pd.id().to_string()); WidgetExt::set_name(&self.container, &pd.id().to_string());
self.unsub self.unsub
.connect_clicked(clone!(shows, pd, sender => move |bttn| { .connect_clicked(clone!(shows, pd, sender => move |bttn| {
on_unsub_button_clicked(shows.clone(), &pd, bttn, sender.clone()); on_unsub_button_clicked(shows.clone(), &pd, bttn, sender.clone());
header.switch_to_normal(); sender.send(Action::HeaderBarNormal).unwrap();
})); }));
self.setup_listbox(pd, sender.clone()); self.setup_listbox(pd, sender.clone());