headerbar: Use Handy widgets

This commit is contained in:
James Westman 2019-10-23 22:40:50 -05:00
parent f632a66d60
commit f6eb3dd90e
4 changed files with 73 additions and 26 deletions

View File

@ -129,43 +129,52 @@ Tobias Bernard
</object> </object>
</child> </child>
</object> </object>
<object class="GtkHeaderBar" id="headerbar"> <object class="HdyHeaderBar" id="headerbar">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="show_close_button">True</property> <property name="show_close_button">True</property>
<property name="centering-policy">strict</property>
<child type="title"> <child type="title">
<object class="GtkBox"> <object class="GtkStack" id="title_stack">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property> <property name="transition_type">crossfade</property>
<child> <child>
<object class="GtkStackSwitcher" id="switch"> <object class="HdySqueezer" id="switch_squeezer">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="halign">center</property> <property name="transition_type">crossfade</property>
<property name="valign">center</property> <child>
<object class="HdyViewSwitcher" id="switch">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="policy">wide</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Podcasts</property>
<style>
<class name="title"/>
</style>
</object>
</child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="show_title"> <object class="GtkLabel" id="show_title">
<property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="no_show_all">True</property> <property name="no_show_all">True</property>
<property name="label" translatable="yes">Show Title</property> <property name="label" translatable="yes">Show Title</property>
<property name="ellipsize">end</property> <property name="ellipsize">end</property>
<property name="track_visited_links">False</property> <property name="track_visited_links">False</property>
<attributes> <style>
<attribute name="weight" value="bold"/> <class name="title" />
</attributes> </style>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -20,6 +20,8 @@
use gio; use gio;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
use libhandy;
use libhandy::prelude::*;
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use failure::Error; use failure::Error;
@ -39,9 +41,12 @@ use crate::i18n::i18n;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
// TODO: Make a proper state machine for the headerbar states // TODO: Make a proper state machine for the headerbar states
pub(crate) struct Header { pub(crate) struct Header {
pub(crate) container: gtk::HeaderBar, pub(crate) container: libhandy::HeaderBar,
pub(crate) switch: gtk::StackSwitcher, pub(crate) switch: libhandy::ViewSwitcher,
pub(crate) bottom_switcher: libhandy::ViewSwitcherBar,
switch_squeezer: libhandy::Squeezer,
back: gtk::Button, back: gtk::Button,
title_stack: gtk::Stack,
show_title: gtk::Label, show_title: gtk::Label,
hamburger: gtk::MenuButton, hamburger: gtk::MenuButton,
add: AddPopover, add: AddPopover,
@ -169,8 +174,10 @@ impl Default for Header {
let menus = gtk::Builder::new_from_resource("/org/gnome/Podcasts/gtk/hamburger.ui"); let menus = gtk::Builder::new_from_resource("/org/gnome/Podcasts/gtk/hamburger.ui");
let header = builder.get_object("headerbar").unwrap(); let header = builder.get_object("headerbar").unwrap();
let switch = builder.get_object("switch").unwrap(); let switch: libhandy::ViewSwitcher = builder.get_object("switch").unwrap();
let back = builder.get_object("back").unwrap(); let back = builder.get_object("back").unwrap();
let title_stack = builder.get_object("title_stack").unwrap();
let switch_squeezer: libhandy::Squeezer = builder.get_object("switch_squeezer").unwrap();
let show_title = builder.get_object("show_title").unwrap(); let show_title = builder.get_object("show_title").unwrap();
// The hamburger menu // The hamburger menu
@ -192,10 +199,17 @@ impl Default for Header {
add: add_button, add: add_button,
}; };
// View switcher bar that goes at the bottom of the window
let switcher = libhandy::ViewSwitcherBar::new();
switcher.set_reveal(false);
Header { Header {
container: header, container: header,
switch, switch,
back, back,
title_stack,
switch_squeezer,
bottom_switcher: switcher,
show_title, show_title,
hamburger, hamburger,
add, add,
@ -215,6 +229,7 @@ impl Header {
pub(crate) fn init(s: &Rc<Self>, content: &Content, sender: &Sender<Action>) { pub(crate) fn init(s: &Rc<Self>, content: &Content, sender: &Sender<Action>) {
let weak = Rc::downgrade(s); let weak = Rc::downgrade(s);
s.bottom_switcher.set_stack(Some(&content.get_stack()));
s.switch.set_stack(Some(&content.get_stack())); s.switch.set_stack(Some(&content.get_stack()));
s.add.entry.connect_changed(clone!(weak => move |_| { s.add.entry.connect_changed(clone!(weak => move |_| {
@ -233,23 +248,29 @@ impl Header {
weak.upgrade().map(|h| h.switch_to_normal()); weak.upgrade().map(|h| h.switch_to_normal());
sender.send(Action::ShowShowsAnimated).expect("Action channel blew up somehow"); sender.send(Action::ShowShowsAnimated).expect("Action channel blew up somehow");
})); }));
s.switch_squeezer
.connect_property_visible_child_notify(clone!(weak => move |_| {
weak.upgrade().map(|h| h.update_bottom_switcher());
}));
s.update_bottom_switcher();
} }
pub(crate) fn switch_to_back(&self, title: &str) { pub(crate) fn switch_to_back(&self, title: &str) {
self.switch.hide();
self.add.toggle.hide(); self.add.toggle.hide();
self.back.show(); self.back.show();
self.set_show_title(title); self.set_show_title(title);
self.show_title.show(); self.title_stack.set_visible_child(&self.show_title);
self.bottom_switcher.set_reveal(false);
self.hamburger.hide(); self.hamburger.hide();
self.dots.show(); self.dots.show();
} }
pub(crate) fn switch_to_normal(&self) { pub(crate) fn switch_to_normal(&self) {
self.switch.show();
self.add.toggle.show(); self.add.toggle.show();
self.back.hide(); self.back.hide();
self.show_title.hide(); self.title_stack.set_visible_child(&self.switch_squeezer);
self.update_bottom_switcher();
self.hamburger.show(); self.hamburger.show();
self.dots.hide(); self.dots.hide();
} }
@ -265,4 +286,10 @@ impl Header {
pub(crate) fn set_secondary_menu(&self, pop: &gtk::PopoverMenu) { pub(crate) fn set_secondary_menu(&self, pop: &gtk::PopoverMenu) {
self.dots.set_popover(Some(pop)); self.dots.set_popover(Some(pop));
} }
fn update_bottom_switcher(&self) {
if let Some(child) = self.switch_squeezer.get_visible_child() {
self.bottom_switcher.set_reveal(child != self.switch);
}
}
} }

View File

@ -54,6 +54,15 @@ impl Content {
stack.add_titled(&home.borrow().get_stack(), "home", &i18n("New")); stack.add_titled(&home.borrow().get_stack(), "home", &i18n("New"));
stack.add_titled(&shows.borrow().get_stack(), "shows", &i18n("Shows")); stack.add_titled(&shows.borrow().get_stack(), "shows", &i18n("Shows"));
stack.set_child_icon_name(
&home.borrow().get_stack(),
Some("document-open-recent-symbolic"),
);
stack.set_child_icon_name(
&shows.borrow().get_stack(),
Some("audio-input-microphone-symbolic"),
);
let con = Content { let con = Content {
stack, stack,
shows, shows,

View File

@ -124,6 +124,8 @@ impl MainWindow {
// Add the player to the main Box // Add the player to the main Box
wrap.add(&player.action_bar); wrap.add(&player.action_bar);
wrap.add(&header.bottom_switcher);
let updater = RefCell::new(None); let updater = RefCell::new(None);
window.add(&wrap); window.add(&wrap);