2022-01-24 20:20:33 +01:00
|
|
|
// Copyright 2022 System76 <info@system76.com>
|
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
|
|
|
|
use crate::components::{InfoButton, InfoButtonInput, InfoButtonOutput};
|
|
|
|
|
use ccs::*;
|
|
|
|
|
use gtk::prelude::*;
|
|
|
|
|
|
|
|
|
|
/// An input event that is used to update the model.
|
|
|
|
|
pub enum AppEvent {
|
|
|
|
|
Destroy,
|
|
|
|
|
Increment,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
component! {
|
|
|
|
|
/// The model where component state is stored.
|
|
|
|
|
#[derive(Default)]
|
2022-01-26 11:30:58 +01:00
|
|
|
pub struct App {
|
2022-01-24 20:20:33 +01:00
|
|
|
pub counter: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Widgets that are initialized in the view.
|
2022-01-26 11:30:58 +01:00
|
|
|
pub struct AppWidgets {
|
2022-01-24 20:20:33 +01:00
|
|
|
list: gtk::ListBox,
|
|
|
|
|
destroyable: Option<Handle<gtk::Box, InfoButtonInput>>,
|
|
|
|
|
counter: Handle<gtk::Box, InfoButtonInput>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Input = AppEvent;
|
|
|
|
|
type Output = ();
|
2022-01-26 11:30:58 +01:00
|
|
|
type Root = gtk::ApplicationWindow {
|
|
|
|
|
Default::default()
|
|
|
|
|
};
|
2022-01-24 20:20:33 +01:00
|
|
|
|
2022-01-26 11:30:58 +01:00
|
|
|
fn init(app: gtk::Application, root, input, output) {
|
2022-01-24 20:20:33 +01:00
|
|
|
let button_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);
|
|
|
|
|
|
2022-01-26 11:30:58 +01:00
|
|
|
let destroyable = InfoButton::init((String::new(), "Destroy".into(), button_group.clone()))
|
2022-01-24 20:20:33 +01:00
|
|
|
.forward(input.clone(), |event| match event {
|
|
|
|
|
InfoButtonOutput::Clicked => AppEvent::Destroy,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Instruct the component to update its description.
|
|
|
|
|
let _ = destroyable.emit(InfoButtonInput::SetDescription(
|
|
|
|
|
"Click this button to destroy me".into(),
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
// Create a counter component, too.
|
2022-01-26 11:30:58 +01:00
|
|
|
let counter = InfoButton::init(("Click me too".into(), "Click".into(), button_group))
|
2022-01-24 20:20:33 +01:00
|
|
|
.forward(input.clone(), |event| match event {
|
|
|
|
|
InfoButtonOutput::Clicked => AppEvent::Increment,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ccs::view! {
|
2022-01-26 11:30:58 +01:00
|
|
|
container = gtk::Box {
|
|
|
|
|
set_halign: gtk::Align::Center,
|
|
|
|
|
set_size_request: args!(400, -1),
|
|
|
|
|
set_orientation: gtk::Orientation::Vertical,
|
|
|
|
|
|
|
|
|
|
append: list = >k::ListBox {
|
|
|
|
|
set_selection_mode: gtk::SelectionMode::None,
|
|
|
|
|
set_hexpand: true,
|
|
|
|
|
|
|
|
|
|
append: destroyable.widget(),
|
|
|
|
|
append: counter.widget(),
|
2022-01-24 20:20:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-26 11:30:58 +01:00
|
|
|
root.set_application(Some(&app));
|
|
|
|
|
root.set_child(Some(&container));
|
|
|
|
|
|
|
|
|
|
root.show();
|
2022-01-24 20:20:33 +01:00
|
|
|
|
2022-01-26 11:30:58 +01:00
|
|
|
ComponentInner {
|
|
|
|
|
model: Self::default(),
|
|
|
|
|
widgets: AppWidgets { list, destroyable: Some(destroyable), counter },
|
|
|
|
|
input,
|
|
|
|
|
output
|
|
|
|
|
}
|
2022-01-24 20:20:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Updates the view
|
2022-01-26 11:30:58 +01:00
|
|
|
fn update(component, event) {
|
|
|
|
|
let &mut ComponentInner { ref mut model, ref mut widgets, .. } = component;
|
|
|
|
|
|
2022-01-24 20:20:33 +01:00
|
|
|
match event {
|
|
|
|
|
AppEvent::Increment => {
|
2022-01-26 11:30:58 +01:00
|
|
|
model.counter += 1;
|
2022-01-24 20:20:33 +01:00
|
|
|
|
|
|
|
|
widgets
|
|
|
|
|
.counter
|
|
|
|
|
.emit(InfoButtonInput::SetDescription(format!(
|
|
|
|
|
"Clicked {} times",
|
2022-01-26 11:30:58 +01:00
|
|
|
model.counter
|
2022-01-24 20:20:33 +01:00
|
|
|
)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppEvent::Destroy => {
|
|
|
|
|
// Components are kept alive by their root GTK widget.
|
|
|
|
|
if let Some(handle) = widgets.destroyable.take() {
|
|
|
|
|
if let Some(parent) = handle.widget().parent() {
|
|
|
|
|
widgets.list.remove(&parent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|