117 lines
3.5 KiB
Rust
117 lines
3.5 KiB
Rust
|
/*
|
||
|
Copyright 2023, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
||
|
|
||
|
This file is part of Screenplay.
|
||
|
|
||
|
Screenplay is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||
|
|
||
|
Screenplay is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License along with Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
use gtk::prelude::*;
|
||
|
|
||
|
#[derive(Clone, Debug)]
|
||
|
pub enum Action {
|
||
|
SelectPage(usize),
|
||
|
Deselect,
|
||
|
}
|
||
|
|
||
|
#[derive(Clone, Debug)]
|
||
|
pub struct Error;
|
||
|
|
||
|
#[derive(Clone)]
|
||
|
pub struct Screen {
|
||
|
pub title: String,
|
||
|
pub widget: gtk::Widget,
|
||
|
pub adjustments: Vec<gtk::Widget>,
|
||
|
}
|
||
|
|
||
|
#[derive(Clone)]
|
||
|
pub struct Screenplay {
|
||
|
frame: gtk::Frame,
|
||
|
screens: Vec<Screen>,
|
||
|
}
|
||
|
|
||
|
impl Screenplay {
|
||
|
pub fn new(gtk_app: >k::Application, screens: Vec<Screen>) -> Result<Self, Error> {
|
||
|
let window = gtk::ApplicationWindow::new(gtk_app);
|
||
|
window.show();
|
||
|
|
||
|
let (sender, receiver) = gtk::glib::MainContext::channel(gtk::glib::PRIORITY_DEFAULT);
|
||
|
|
||
|
let layout = gtk::Box::builder()
|
||
|
.orientation(gtk::Orientation::Horizontal)
|
||
|
.build();
|
||
|
window.set_child(Some(&layout));
|
||
|
|
||
|
let listbox = gtk::ListBox::builder()
|
||
|
.activate_on_single_click(true)
|
||
|
.show_separators(true)
|
||
|
.focusable(false)
|
||
|
.build();
|
||
|
|
||
|
let frame = gtk::Frame::builder()
|
||
|
.height_request(500)
|
||
|
.width_request(500)
|
||
|
.build();
|
||
|
|
||
|
layout.append(&listbox);
|
||
|
layout.append(&frame);
|
||
|
|
||
|
listbox.connect_row_activated(move |_, row| {
|
||
|
match row.index() {
|
||
|
-1 => sender.send(Action::Deselect),
|
||
|
idx => sender.send(Action::SelectPage(idx as usize)),
|
||
|
}
|
||
|
.unwrap()
|
||
|
});
|
||
|
|
||
|
screens.iter().for_each(|Screen { title, .. }| {
|
||
|
listbox.append(
|
||
|
>k::ListBoxRow::builder()
|
||
|
.child(>k::Label::new(Some(title.as_ref())))
|
||
|
.build(),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
let storybook = Self { frame, screens };
|
||
|
|
||
|
{
|
||
|
let mut storybook = storybook.clone();
|
||
|
receiver.attach(None, move |message| storybook.process_action(message));
|
||
|
}
|
||
|
|
||
|
Ok(storybook)
|
||
|
}
|
||
|
|
||
|
fn process_action(&mut self, message: Action) -> Continue {
|
||
|
let nothing: Option<>k::Widget> = None;
|
||
|
match message {
|
||
|
Action::SelectPage(index) => match self.screens.get(index) {
|
||
|
Some(Screen {
|
||
|
widget,
|
||
|
adjustments,
|
||
|
..
|
||
|
}) => {
|
||
|
let b = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||
|
let control_box = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||
|
b.append(widget);
|
||
|
b.append(&control_box);
|
||
|
|
||
|
adjustments
|
||
|
.iter()
|
||
|
.for_each(|control| control_box.append(control));
|
||
|
|
||
|
self.frame.set_child(Some(&b));
|
||
|
}
|
||
|
None => self.frame.set_child(nothing),
|
||
|
},
|
||
|
Action::Deselect => self.frame.set_child(nothing),
|
||
|
}
|
||
|
|
||
|
Continue(true)
|
||
|
}
|
||
|
}
|