refactor!(ccs): Improvements to design
This commit is contained in:
parent
148ffc6dae
commit
dff9265e35
7 changed files with 157 additions and 128 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
This library is a GTK4 GUI framework inspired by [Relm](https://github.com/antoyo/relm), which is inspired by [Elm](https://guide.elm-lang.org/architecture/). The philosophy for this framework is to isolate custom widgets into reusable components. You start with a custom `Model` type that implements `Component`, which is used to register a component with an optional argument. On registration, the model is used to construct the view and its widgets in the `init_view()` function. An event-handler is also spawned to handle events from both the component and any component emitting events to it. Those events are received and handled in the `update()` function. Both the `init_view()` and `update()` methods also have access to an outbound sender, which the caller can forward and consume however desired. See the examples directory for a demonstration of how to create a component.
|
||||
|
||||
## Defining a Component
|
||||
## Using a Macro to Define a Component
|
||||
|
||||
The simplest way to define a component is to use the `component!()` macro.
|
||||
|
||||
|
|
@ -13,14 +13,13 @@ pub enum MyCustomInputMessage {
|
|||
}
|
||||
|
||||
component! {
|
||||
// The `()` is the args parameter accepted by `init_view()`
|
||||
// and `Component::register()`.
|
||||
pub struct MyCustomModel(()) {
|
||||
// The model stores the state of this component.
|
||||
pub struct MyCustomModel {
|
||||
pub state: String,
|
||||
}
|
||||
|
||||
// The `gtk::Box` is the root widget returned in `init_view()`.
|
||||
pub struct MyCustomWidgets(gtk::Box) {
|
||||
// Widgets managed by the view are stored here.
|
||||
pub struct MyCustomWidgets {
|
||||
description: gtk::Label,
|
||||
}
|
||||
|
||||
|
|
@ -30,24 +29,35 @@ component! {
|
|||
// The type of the output sender
|
||||
type Output = ();
|
||||
|
||||
// `self` is `MyCustomModel`, and must return `(MyCustomWidget, RootWidget)`
|
||||
fn init_view(self, args, input, output) {
|
||||
// Declares the root widget and how it should be constructed.
|
||||
type Root = gtk::Box {
|
||||
ccs::view! {
|
||||
root = gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
append: description = >k::Label {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(MyCustomWidgets { description }, root)
|
||||
root
|
||||
};
|
||||
|
||||
// Constructs the inner component's model and widgets, using the
|
||||
// initial parameter given by `args`.
|
||||
fn init(args: (), root, input, output) {
|
||||
let description = gtk::Label::new();
|
||||
|
||||
root.append(&description);
|
||||
|
||||
ComponentInner {
|
||||
model: MyCustomModel { state: String::new() },
|
||||
widgets: MyCustomWidgets { description },
|
||||
input,
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
// Where events are received, with `self` also being `MyCustomModel`, and
|
||||
// `widgets` is `MyCustomInputMessage`. `event` is `MyCustonInputMessage`.
|
||||
fn update(self, widgets, event, input, output) {
|
||||
// Where events are received, with `component` is the `ComponentInner`,
|
||||
// and `event` is a `MyCustomInputMessage` which was just received.
|
||||
fn update(component, event) {
|
||||
match event {
|
||||
MyCustomInputMessage::Variant1 => {
|
||||
|
||||
|
|
@ -64,8 +74,7 @@ component! {
|
|||
Components can be created and have their output events forwarded:
|
||||
|
||||
```rs
|
||||
let counter = InfoButton::default()
|
||||
.register("Clicked 0 times".into(), "Click".into())
|
||||
let counter = InfoButton::init("Clicked 0 times".into(), "Click".into())
|
||||
.forward(input.clone(), |event| match event {
|
||||
InfoButtonOutput::Clicked => AppEvent::Increment
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue