1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
//! Defines traits and data types used to efficiently generating widgets from collections.
use gtk::glib::Sender;
use gtk::prelude::WidgetExt;
pub mod collections;
pub mod positions;
mod widgets;
pub use collections::*;
/// Define behavior to create, update and remove widgets according to
/// data stored in a factory.
pub trait FactoryPrototype: Sized {
/// Factory container that stores the data.
type Factory: Factory<Self, Self::View>;
/// Type that stores all widgets needed to update them
/// in the [`view`](FactoryPrototype::view) function.
type Widgets: std::fmt::Debug;
/// Outermost type of the newly created widgets.
/// Similar to the `Root` type in [`crate::Widgets`].
type Root: WidgetExt;
/// Widget that the generated widgets are added to.
type View: FactoryView<Self::Root>;
/// Message type used to send messages back to the component or app
/// where this factory is used
type Msg;
/// Create new widgets when self is inserted into the factory.
fn init_view(
&self,
key: &<Self::Factory as Factory<Self, Self::View>>::Key,
sender: Sender<Self::Msg>,
) -> Self::Widgets;
/// Set the widget position upon creation, useful for [`gtk::Grid`] or similar.
fn position(
&self,
key: &<Self::Factory as Factory<Self, Self::View>>::Key,
) -> <Self::View as FactoryView<Self::Root>>::Position;
/// Function called when self is modified.
fn view(
&self,
key: &<Self::Factory as Factory<Self, Self::View>>::Key,
widgets: &Self::Widgets,
);
/// Get the outermost widget from the widgets.
fn root_widget(widgets: &Self::Widgets) -> &Self::Root;
}
/// A container that is a able to efficiently update, generate and remove widgets
/// that represent the data stored in the container.
pub trait Factory<Data, View>
where
Data: FactoryPrototype<View = View>,
View: FactoryView<Data::Root>,
{
/// Key that provides additional information for the [`FactoryPrototype`] functions.
type Key: ?Sized;
/// Efficiently update the view according to data changes.
fn generate(&self, view: &View, sender: Sender<Data::Msg>);
}
/*/// A trait to simplify the implementation of [`FactoryView`] for most
/// GTK4 widgets.
trait SimpleFactoryView<Widget: std::fmt::Debug> {
/// Position type used by this widget.
///
/// For example [`GridPosition`] for [`gtk::Grid`] or `()` for [`gtk::Box`]
type Position;
/// Adds a new widget to self at the end.
fn add(&self, widget: &Widget, position: &Self::Position);
/// Removes a widget from self at the end.
fn remove(&self, widget: &Widget);
}*/
/// A trait implemented for GTK4 widgets that allows a factory to create and remove widgets.
pub trait FactoryView<Widget> {
/// Widget type that's stored inside a factory data type.
type Root: std::fmt::Debug;
/// Position type used by this widget.
///
/// For example [`GridPosition`](positions::GridPosition) for [`gtk::Grid`] or `()` for [`gtk::Box`]
type Position;
/// Adds a new widget to self at the end.
fn add(&self, widget: &Widget, position: &Self::Position) -> Self::Root;
/// Removes a widget from self at the end.
fn remove(&self, widget: &Self::Root);
}
/*impl<Widget, M> FactoryView<Widget> for M
where
M: SimpleFactoryView<Widget>,
Widget: Clone + std::fmt::Debug,
{
type Position = M::Position;
type Root = Widget;
fn add(&self, widget: &Widget, position: &Self::Position) -> Self::Root {
self.add(widget, position);
widget.clone()
}
fn remove(&self, widget: &Widget) {
self.remove(widget);
}
}*/
/// Extends [`FactoryView`] for containers that work similar to lists.
/// This means that the container can insert widgets before and after other
/// widgets.
pub trait FactoryListView<Widget>
where
Self: FactoryView<Widget>,
{
/// Insert a widget after another widget.
fn insert_after(&self, widget: &Widget, other: &Self::Root) -> Self::Root;
/// Add an widget to the front.
fn push_front(&self, widget: &Widget) -> Self::Root;
}