mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Replace stack with new navigator widget
This commit is contained in:
parent
cefd7dad95
commit
9a9a181739
8 changed files with 268 additions and 206 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
use super::*;
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
|
|
@ -9,10 +10,11 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct EnsembleScreen {
|
pub struct EnsembleScreen {
|
||||||
pub widget: gtk::Box,
|
backend: Rc<Backend>,
|
||||||
|
widget: gtk::Box,
|
||||||
stack: gtk::Stack,
|
stack: gtk::Stack,
|
||||||
recording_list: Rc<List<RecordingDescription>>,
|
recording_list: Rc<List<RecordingDescription>>,
|
||||||
back: RefCell<Option<Box<dyn Fn() -> () + 'static>>>,
|
navigator: RefCell<Option<Rc<Navigator>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnsembleScreen {
|
impl EnsembleScreen {
|
||||||
|
|
@ -59,10 +61,11 @@ impl EnsembleScreen {
|
||||||
recording_frame.add(&recording_list.widget.clone());
|
recording_frame.add(&recording_list.widget.clone());
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
|
backend,
|
||||||
widget,
|
widget,
|
||||||
stack,
|
stack,
|
||||||
recording_list,
|
recording_list,
|
||||||
back: RefCell::new(None),
|
navigator: RefCell::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
search_entry.connect_search_changed(clone!(@strong result => move |_| {
|
search_entry.connect_search_changed(clone!(@strong result => move |_| {
|
||||||
|
|
@ -70,15 +73,26 @@ impl EnsembleScreen {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
back_button.connect_clicked(clone!(@strong result => move |_| {
|
back_button.connect_clicked(clone!(@strong result => move |_| {
|
||||||
if let Some(back) = &*result.back.borrow() {
|
let navigator = result.navigator.borrow().clone();
|
||||||
back();
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.pop();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
result
|
||||||
|
.recording_list
|
||||||
|
.set_selected(clone!(@strong result => move |recording| {
|
||||||
|
let navigator = result.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.push(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
let context = glib::MainContext::default();
|
let context = glib::MainContext::default();
|
||||||
let clone = result.clone();
|
let clone = result.clone();
|
||||||
context.spawn_local(async move {
|
context.spawn_local(async move {
|
||||||
let recordings = backend
|
let recordings = clone
|
||||||
|
.backend
|
||||||
.get_recordings_for_ensemble(ensemble.id)
|
.get_recordings_for_ensemble(ensemble.id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -93,18 +107,18 @@ impl EnsembleScreen {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_back<B>(&self, back: B)
|
impl NavigatorScreen for EnsembleScreen {
|
||||||
where
|
fn attach_navigator(&self, navigator: Rc<Navigator>) {
|
||||||
B: Fn() -> () + 'static,
|
self.navigator.replace(Some(navigator));
|
||||||
{
|
|
||||||
self.back.replace(Some(Box::new(back)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_recording_selected<S>(&self, selected: S)
|
fn get_widget(&self) -> gtk::Widget {
|
||||||
where
|
self.widget.clone().upcast()
|
||||||
S: Fn(&RecordingDescription) -> () + 'static,
|
}
|
||||||
{
|
|
||||||
self.recording_list.set_selected(selected);
|
fn detach_navigator(&self) {
|
||||||
|
self.navigator.replace(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use super::*;
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
|
|
@ -9,11 +10,12 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct PersonScreen {
|
pub struct PersonScreen {
|
||||||
pub widget: gtk::Box,
|
backend: Rc<Backend>,
|
||||||
|
widget: gtk::Box,
|
||||||
stack: gtk::Stack,
|
stack: gtk::Stack,
|
||||||
work_list: Rc<List<WorkDescription>>,
|
work_list: Rc<List<WorkDescription>>,
|
||||||
recording_list: Rc<List<RecordingDescription>>,
|
recording_list: Rc<List<RecordingDescription>>,
|
||||||
back: RefCell<Option<Box<dyn Fn() -> () + 'static>>>,
|
navigator: RefCell<Option<Rc<Navigator>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PersonScreen {
|
impl PersonScreen {
|
||||||
|
|
@ -77,11 +79,12 @@ impl PersonScreen {
|
||||||
recording_frame.add(&recording_list.widget);
|
recording_frame.add(&recording_list.widget);
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
|
backend,
|
||||||
widget,
|
widget,
|
||||||
stack,
|
stack,
|
||||||
work_list,
|
work_list,
|
||||||
recording_list,
|
recording_list,
|
||||||
back: RefCell::new(None),
|
navigator: RefCell::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
search_entry.connect_search_changed(clone!(@strong result => move |_| {
|
search_entry.connect_search_changed(clone!(@strong result => move |_| {
|
||||||
|
|
@ -90,16 +93,43 @@ impl PersonScreen {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
back_button.connect_clicked(clone!(@strong result => move |_| {
|
back_button.connect_clicked(clone!(@strong result => move |_| {
|
||||||
if let Some(back) = &*result.back.borrow() {
|
let navigator = result.navigator.borrow().clone();
|
||||||
back();
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.clone().pop();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
result
|
||||||
|
.work_list
|
||||||
|
.set_selected(clone!(@strong result => move |work| {
|
||||||
|
let navigator = result.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.push(WorkScreen::new(result.backend.clone(), work.clone()));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
result
|
||||||
|
.recording_list
|
||||||
|
.set_selected(clone!(@strong result => move |recording| {
|
||||||
|
let navigator = result.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.push(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
let context = glib::MainContext::default();
|
let context = glib::MainContext::default();
|
||||||
let clone = result.clone();
|
let clone = result.clone();
|
||||||
context.spawn_local(async move {
|
context.spawn_local(async move {
|
||||||
let works = backend.get_work_descriptions(person.id).await.unwrap();
|
let works = clone
|
||||||
let recordings = backend.get_recordings_for_person(person.id).await.unwrap();
|
.backend
|
||||||
|
.get_work_descriptions(person.id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let recordings = clone
|
||||||
|
.backend
|
||||||
|
.get_recordings_for_person(person.id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if works.is_empty() && recordings.is_empty() {
|
if works.is_empty() && recordings.is_empty() {
|
||||||
clone.stack.set_visible_child_name("nothing");
|
clone.stack.set_visible_child_name("nothing");
|
||||||
|
|
@ -122,25 +152,18 @@ impl PersonScreen {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_back<B>(&self, back: B)
|
impl NavigatorScreen for PersonScreen {
|
||||||
where
|
fn attach_navigator(&self, navigator: Rc<Navigator>) {
|
||||||
B: Fn() -> () + 'static,
|
self.navigator.replace(Some(navigator));
|
||||||
{
|
|
||||||
self.back.replace(Some(Box::new(back)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_work_selected<S>(&self, selected: S)
|
fn get_widget(&self) -> gtk::Widget {
|
||||||
where
|
self.widget.clone().upcast()
|
||||||
S: Fn(&WorkDescription) -> () + 'static,
|
|
||||||
{
|
|
||||||
self.work_list.set_selected(selected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_recording_selected<S>(&self, selected: S)
|
fn detach_navigator(&self) {
|
||||||
where
|
self.navigator.replace(None);
|
||||||
S: Fn(&RecordingDescription) -> () + 'static,
|
|
||||||
{
|
|
||||||
self.recording_list.set_selected(selected);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
|
use crate::widgets::*;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk_macros::get_widget;
|
use gtk_macros::get_widget;
|
||||||
|
|
@ -8,8 +9,8 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct RecordingScreen {
|
pub struct RecordingScreen {
|
||||||
pub widget: gtk::Box,
|
widget: gtk::Box,
|
||||||
back: RefCell<Option<Box<dyn Fn() -> () + 'static>>>,
|
navigator: RefCell<Option<Rc<Navigator>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecordingScreen {
|
impl RecordingScreen {
|
||||||
|
|
@ -27,22 +28,30 @@ impl RecordingScreen {
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
widget,
|
widget,
|
||||||
back: RefCell::new(None),
|
navigator: RefCell::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
back_button.connect_clicked(clone!(@strong result => move |_| {
|
back_button.connect_clicked(clone!(@strong result => move |_| {
|
||||||
if let Some(back) = &*result.back.borrow() {
|
let navigator = result.navigator.borrow().clone();
|
||||||
back();
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.clone().pop();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_back<B>(&self, back: B)
|
impl NavigatorScreen for RecordingScreen {
|
||||||
where
|
fn attach_navigator(&self, navigator: Rc<Navigator>) {
|
||||||
B: Fn() -> () + 'static,
|
self.navigator.replace(Some(navigator));
|
||||||
{
|
}
|
||||||
self.back.replace(Some(Box::new(back)));
|
|
||||||
|
fn get_widget(&self) -> gtk::Widget {
|
||||||
|
self.widget.clone().upcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detach_navigator(&self) {
|
||||||
|
self.navigator.replace(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use super::*;
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
|
|
@ -9,10 +10,11 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct WorkScreen {
|
pub struct WorkScreen {
|
||||||
pub widget: gtk::Box,
|
backend: Rc<Backend>,
|
||||||
|
widget: gtk::Box,
|
||||||
stack: gtk::Stack,
|
stack: gtk::Stack,
|
||||||
recording_list: Rc<List<RecordingDescription>>,
|
recording_list: Rc<List<RecordingDescription>>,
|
||||||
back: RefCell<Option<Box<dyn Fn() -> () + 'static>>>,
|
navigator: RefCell<Option<Rc<Navigator>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkScreen {
|
impl WorkScreen {
|
||||||
|
|
@ -59,10 +61,11 @@ impl WorkScreen {
|
||||||
recording_frame.add(&recording_list.widget);
|
recording_frame.add(&recording_list.widget);
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
|
backend,
|
||||||
widget,
|
widget,
|
||||||
stack,
|
stack,
|
||||||
recording_list,
|
recording_list,
|
||||||
back: RefCell::new(None),
|
navigator: RefCell::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
search_entry.connect_search_changed(clone!(@strong result => move |_| {
|
search_entry.connect_search_changed(clone!(@strong result => move |_| {
|
||||||
|
|
@ -70,15 +73,29 @@ impl WorkScreen {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
back_button.connect_clicked(clone!(@strong result => move |_| {
|
back_button.connect_clicked(clone!(@strong result => move |_| {
|
||||||
if let Some(back) = &*result.back.borrow() {
|
let navigator = result.navigator.borrow().clone();
|
||||||
back();
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.clone().pop();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
result
|
||||||
|
.recording_list
|
||||||
|
.set_selected(clone!(@strong result => move |recording| {
|
||||||
|
let navigator = result.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.push(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
let context = glib::MainContext::default();
|
let context = glib::MainContext::default();
|
||||||
let clone = result.clone();
|
let clone = result.clone();
|
||||||
context.spawn_local(async move {
|
context.spawn_local(async move {
|
||||||
let recordings = backend.get_recordings_for_work(work.id).await.unwrap();
|
let recordings = clone
|
||||||
|
.backend
|
||||||
|
.get_recordings_for_work(work.id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if recordings.is_empty() {
|
if recordings.is_empty() {
|
||||||
clone.stack.set_visible_child_name("nothing");
|
clone.stack.set_visible_child_name("nothing");
|
||||||
|
|
@ -90,18 +107,18 @@ impl WorkScreen {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_back<B>(&self, back: B)
|
impl NavigatorScreen for WorkScreen {
|
||||||
where
|
fn attach_navigator(&self, navigator: Rc<Navigator>) {
|
||||||
B: Fn() -> () + 'static,
|
self.navigator.replace(Some(navigator));
|
||||||
{
|
|
||||||
self.back.replace(Some(Box::new(back)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_recording_selected<S>(&self, selected: S)
|
fn get_widget(&self) -> gtk::Widget {
|
||||||
where
|
self.widget.clone().upcast()
|
||||||
S: Fn(&RecordingDescription) -> () + 'static,
|
}
|
||||||
{
|
|
||||||
self.recording_list.set_selected(selected);
|
fn detach_navigator(&self) {
|
||||||
|
self.navigator.replace(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub use list::*;
|
pub use list::*;
|
||||||
|
|
||||||
|
pub mod navigator;
|
||||||
|
pub use navigator::*;
|
||||||
|
|
||||||
pub mod person_list;
|
pub mod person_list;
|
||||||
pub use person_list::*;
|
pub use person_list::*;
|
||||||
|
|
||||||
|
|
@ -9,6 +12,3 @@ pub use poe_list::*;
|
||||||
|
|
||||||
pub mod selector_row;
|
pub mod selector_row;
|
||||||
pub use selector_row::*;
|
pub use selector_row::*;
|
||||||
|
|
||||||
pub mod stack;
|
|
||||||
pub use stack::*;
|
|
||||||
|
|
|
||||||
130
src/widgets/navigator.rs
Normal file
130
src/widgets/navigator.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
use glib::clone;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub trait NavigatorScreen {
|
||||||
|
fn attach_navigator(&self, navigator: Rc<Navigator>);
|
||||||
|
fn get_widget(&self) -> gtk::Widget;
|
||||||
|
fn detach_navigator(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Navigator {
|
||||||
|
pub widget: gtk::Stack,
|
||||||
|
screens: RefCell<Vec<Rc<dyn NavigatorScreen>>>,
|
||||||
|
old_screens: RefCell<Vec<Rc<dyn NavigatorScreen>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Navigator {
|
||||||
|
pub fn new<W>(empty_screen: &W) -> Rc<Self>
|
||||||
|
where
|
||||||
|
W: IsA<gtk::Widget>,
|
||||||
|
{
|
||||||
|
let widget = gtk::Stack::new();
|
||||||
|
widget.set_transition_type(gtk::StackTransitionType::Crossfade);
|
||||||
|
widget.set_hexpand(true);
|
||||||
|
widget.add_named(empty_screen, "empty_screen");
|
||||||
|
widget.show();
|
||||||
|
|
||||||
|
let result = Rc::new(Self {
|
||||||
|
widget,
|
||||||
|
screens: RefCell::new(Vec::new()),
|
||||||
|
old_screens: RefCell::new(Vec::new()),
|
||||||
|
});
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
result.widget.connect_notify_unsafe(
|
||||||
|
Some("transition-running"),
|
||||||
|
clone!(@strong result => move |_, _| {
|
||||||
|
if !result.widget.get_transition_running() {
|
||||||
|
result.clear_old_screens();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push<S>(self: Rc<Self>, screen: Rc<S>)
|
||||||
|
where
|
||||||
|
S: NavigatorScreen + 'static,
|
||||||
|
{
|
||||||
|
if let Some(screen) = self.screens.borrow().last() {
|
||||||
|
screen.detach_navigator();
|
||||||
|
}
|
||||||
|
|
||||||
|
let widget = screen.get_widget();
|
||||||
|
self.widget.add(&widget);
|
||||||
|
self.widget.set_visible_child(&widget);
|
||||||
|
|
||||||
|
screen.attach_navigator(self.clone());
|
||||||
|
self.screens.borrow_mut().push(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop(self: Rc<Self>) {
|
||||||
|
let popped = if let Some(screen) = self.screens.borrow_mut().pop() {
|
||||||
|
screen.detach_navigator();
|
||||||
|
self.old_screens.borrow_mut().push(screen);
|
||||||
|
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if popped {
|
||||||
|
if let Some(screen) = self.screens.borrow().last() {
|
||||||
|
let widget = screen.get_widget();
|
||||||
|
self.widget.set_visible_child(&widget);
|
||||||
|
|
||||||
|
screen.attach_navigator(self.clone());
|
||||||
|
} else {
|
||||||
|
self.widget.set_visible_child_name("empty_screen");
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.widget.get_transition_running() {
|
||||||
|
self.clear_old_screens();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace<S>(self: Rc<Self>, screen: Rc<S>)
|
||||||
|
where
|
||||||
|
S: NavigatorScreen + 'static,
|
||||||
|
{
|
||||||
|
for screen in self.screens.replace(Vec::new()) {
|
||||||
|
screen.detach_navigator();
|
||||||
|
self.old_screens.borrow_mut().push(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
let widget = screen.get_widget();
|
||||||
|
self.widget.add(&widget);
|
||||||
|
self.widget.set_visible_child(&widget);
|
||||||
|
|
||||||
|
screen.attach_navigator(self.clone());
|
||||||
|
self.screens.borrow_mut().push(screen);
|
||||||
|
|
||||||
|
if !self.widget.get_transition_running() {
|
||||||
|
self.clear_old_screens();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&self) {
|
||||||
|
for screen in self.screens.replace(Vec::new()) {
|
||||||
|
screen.detach_navigator();
|
||||||
|
self.old_screens.borrow_mut().push(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.widget.get_transition_running() {
|
||||||
|
self.clear_old_screens();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_old_screens(&self) {
|
||||||
|
for screen in self.old_screens.borrow().iter() {
|
||||||
|
self.widget.remove(&screen.get_widget());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.old_screens.borrow_mut().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
use glib::clone;
|
|
||||||
use gtk::prelude::*;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
pub struct Stack {
|
|
||||||
pub widget: gtk::Stack,
|
|
||||||
old_children: RefCell<Vec<gtk::Widget>>,
|
|
||||||
current_child: RefCell<Option<gtk::Widget>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Stack {
|
|
||||||
pub fn new<W>(empty_screen: &W) -> Self
|
|
||||||
where
|
|
||||||
W: IsA<gtk::Widget>,
|
|
||||||
{
|
|
||||||
let old_children = RefCell::new(Vec::new());
|
|
||||||
|
|
||||||
let widget = gtk::Stack::new();
|
|
||||||
widget.set_transition_type(gtk::StackTransitionType::Crossfade);
|
|
||||||
widget.set_hexpand(true);
|
|
||||||
widget.add_named(empty_screen, "empty_screen");
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
widget.connect_notify_unsafe(
|
|
||||||
Some("transition-running"),
|
|
||||||
clone!(@strong old_children => move |stack, _| {
|
|
||||||
for child in old_children.borrow().iter() {
|
|
||||||
stack.remove(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
old_children.borrow_mut().clear();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
widget.show();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
widget: widget.clone(),
|
|
||||||
old_children,
|
|
||||||
current_child: RefCell::new(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_child<W>(&self, child: W)
|
|
||||||
where
|
|
||||||
W: IsA<gtk::Widget>,
|
|
||||||
{
|
|
||||||
if let Some(child) = self.current_child.borrow_mut().take() {
|
|
||||||
self.old_children.borrow_mut().push(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current_child.replace(Some(child.clone().upcast()));
|
|
||||||
self.widget.add(&child);
|
|
||||||
self.widget.set_visible_child(&child);
|
|
||||||
|
|
||||||
if !self.widget.get_transition_running() {
|
|
||||||
for child in self.old_children.borrow().iter() {
|
|
||||||
self.widget.remove(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.old_children.borrow_mut().clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset_child(&self) {
|
|
||||||
self.widget.set_visible_child_name("empty_screen");
|
|
||||||
|
|
||||||
if !self.widget.get_transition_running() {
|
|
||||||
for child in self.old_children.borrow().iter() {
|
|
||||||
self.widget.remove(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.old_children.borrow_mut().clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,7 +15,7 @@ pub struct Window {
|
||||||
leaflet: libhandy::Leaflet,
|
leaflet: libhandy::Leaflet,
|
||||||
sidebar_box: gtk::Box,
|
sidebar_box: gtk::Box,
|
||||||
poe_list: Rc<PoeList>,
|
poe_list: Rc<PoeList>,
|
||||||
stack: Stack,
|
navigator: Rc<Navigator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
|
@ -29,7 +29,7 @@ impl Window {
|
||||||
|
|
||||||
let backend = Rc::new(Backend::new("test.sqlite"));
|
let backend = Rc::new(Backend::new("test.sqlite"));
|
||||||
let poe_list = PoeList::new(backend.clone());
|
let poe_list = PoeList::new(backend.clone());
|
||||||
let stack = Stack::new(&empty_screen);
|
let navigator = Navigator::new(&empty_screen);
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
backend,
|
backend,
|
||||||
|
|
@ -37,78 +37,24 @@ impl Window {
|
||||||
leaflet,
|
leaflet,
|
||||||
sidebar_box,
|
sidebar_box,
|
||||||
poe_list,
|
poe_list,
|
||||||
stack,
|
navigator,
|
||||||
});
|
});
|
||||||
|
|
||||||
result
|
result
|
||||||
.poe_list
|
.poe_list
|
||||||
.set_selected(clone!(@strong result => move |poe| {
|
.set_selected(clone!(@strong result => move |poe| {
|
||||||
result.leaflet.set_visible_child(&result.stack.widget);
|
result.leaflet.set_visible_child(&result.navigator.widget);
|
||||||
match poe {
|
match poe {
|
||||||
PersonOrEnsemble::Person(person) => {
|
PersonOrEnsemble::Person(person) => {
|
||||||
let person_screen = Rc::new(PersonScreen::new(result.backend.clone(), person.clone()));
|
result.navigator.clone().replace(PersonScreen::new(result.backend.clone(), person.clone()));
|
||||||
|
|
||||||
person_screen.set_back(clone!(@strong result => move || {
|
|
||||||
result.leaflet.set_visible_child(&result.sidebar_box);
|
|
||||||
result.stack.reset_child();
|
|
||||||
}));
|
|
||||||
|
|
||||||
person_screen.set_work_selected(clone!(@strong result, @strong person_screen => move |work| {
|
|
||||||
let work_screen = Rc::new(WorkScreen::new(result.backend.clone(), work.clone()));
|
|
||||||
|
|
||||||
work_screen.set_back(clone!(@strong result, @strong person_screen => move || {
|
|
||||||
result.stack.set_child(person_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
work_screen.set_recording_selected(clone!(@strong result, @strong work_screen => move |recording| {
|
|
||||||
let recording_screen = RecordingScreen::new(result.backend.clone(), recording.clone());
|
|
||||||
|
|
||||||
recording_screen.set_back(clone!(@strong result, @strong work_screen => move || {
|
|
||||||
result.stack.set_child(work_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
result.stack.set_child(recording_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
result.stack.set_child(work_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
person_screen.set_recording_selected(clone!(@strong result, @strong person_screen => move |recording| {
|
|
||||||
let recording_screen = Rc::new(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
|
||||||
|
|
||||||
recording_screen.set_back(clone!(@strong result, @strong person_screen => move || {
|
|
||||||
result.stack.set_child(person_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
result.stack.set_child(recording_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
result.stack.set_child(person_screen.widget.clone());
|
|
||||||
}
|
}
|
||||||
PersonOrEnsemble::Ensemble(ensemble) => {
|
PersonOrEnsemble::Ensemble(ensemble) => {
|
||||||
let ensemble_screen = EnsembleScreen::new(result.backend.clone(), ensemble.clone());
|
result.navigator.clone().replace(EnsembleScreen::new(result.backend.clone(), ensemble.clone()));
|
||||||
|
|
||||||
ensemble_screen.set_back(clone!(@strong result => move || {
|
|
||||||
result.leaflet.set_visible_child(&result.sidebar_box);
|
|
||||||
result.stack.reset_child();
|
|
||||||
}));
|
|
||||||
|
|
||||||
ensemble_screen.set_recording_selected(clone!(@strong result, @strong ensemble_screen => move |recording| {
|
|
||||||
let recording_screen = Rc::new(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
|
||||||
|
|
||||||
recording_screen.set_back(clone!(@strong result, @strong ensemble_screen => move || {
|
|
||||||
result.stack.set_child(ensemble_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
result.stack.set_child(recording_screen.widget.clone());
|
|
||||||
}));
|
|
||||||
|
|
||||||
result.stack.set_child(ensemble_screen.widget.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
result.leaflet.add(&result.stack.widget);
|
result.leaflet.add(&result.navigator.widget);
|
||||||
result
|
result
|
||||||
.sidebar_box
|
.sidebar_box
|
||||||
.pack_start(&result.poe_list.widget, true, true, 0);
|
.pack_start(&result.poe_list.widget, true, true, 0);
|
||||||
|
|
@ -237,7 +183,7 @@ impl Window {
|
||||||
|
|
||||||
fn reload(&self) {
|
fn reload(&self) {
|
||||||
self.poe_list.clone().reload();
|
self.poe_list.clone().reload();
|
||||||
self.stack.reset_child();
|
self.navigator.reset();
|
||||||
self.leaflet.set_visible_child(&self.sidebar_box);
|
self.leaflet.set_visible_child(&self.sidebar_box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue