relm4/factory/widgets/
traits.rs

1use gtk::prelude::IsA;
2use std::fmt::Debug;
3
4/// A trait implemented for GTK4 widgets that allows a factory to create and remove widgets.
5pub trait FactoryView: IsA<gtk::Widget> {
6    /// The widget returned when inserting a widget.
7    ///
8    /// This doesn't matter on containers like [`gtk::Box`].
9    /// However, widgets such as [`gtk::Stack`] return a [`gtk::StackPage`]
10    /// which might be used to set additional parameters.
11    ///
12    /// Therefore, this "returned widget" is explicitly handled here.
13    type ReturnedWidget: Debug + std::hash::Hash;
14
15    /// Widget type that is attached to the container
16    /// and also the root of the components.
17    type Children: Debug + AsRef<Self::Children>;
18
19    /// Position type used by this widget.
20    ///
21    /// For example [`GridPosition`] for [`gtk::Grid`] or `()` for [`gtk::Box`]
22    ///
23    /// [`GridPosition`]: crate::factory::positions::GridPosition
24    type Position;
25
26    /// Removes a widget.
27    fn factory_remove(&self, widget: &Self::ReturnedWidget);
28    /// Adds a new widget to self at the end.
29    fn factory_append(
30        &self,
31        widget: impl AsRef<Self::Children>,
32        position: &Self::Position,
33    ) -> Self::ReturnedWidget;
34
35    /// Add an widget to the front.
36    fn factory_prepend(
37        &self,
38        widget: impl AsRef<Self::Children>,
39        position: &Self::Position,
40    ) -> Self::ReturnedWidget;
41
42    /// Insert a widget after another widget.
43    fn factory_insert_after(
44        &self,
45        widget: impl AsRef<Self::Children>,
46        position: &Self::Position,
47        other: &Self::ReturnedWidget,
48    ) -> Self::ReturnedWidget;
49
50    /// Converts a returned widget to the children type.
51    ///
52    fn returned_widget_to_child(root_child: &Self::ReturnedWidget) -> Self::Children;
53
54    /// Move an item after another item.
55    fn factory_move_after(&self, widget: &Self::ReturnedWidget, other: &Self::ReturnedWidget);
56
57    /// Move an item to the start.
58    fn factory_move_start(&self, widget: &Self::ReturnedWidget);
59
60    /// Update the position inside positioned containers like [`gtk::Grid`].
61    fn factory_update_position(&self, _widget: &Self::ReturnedWidget, _position: &Self::Position) {}
62}
63
64/// Returns the position of an element inside a
65/// container like [`gtk::Grid`] where the position isn't
66/// clearly defined by the index.
67pub trait Position<Pos, Index> {
68    /// Returns the position.
69    ///
70    /// This function can be called very often
71    /// if widgets are moved a lot, so it should
72    /// be cheap to call.
73    fn position(&self, index: &Index) -> Pos;
74}
75
76impl<C, I> Position<(), I> for C {
77    fn position(&self, _index: &I) {}
78}
79
80/// Returns the position of an element inside a
81/// container like [`gtk::Grid`] where the position isn't
82/// clearly defined by the index.
83///
84/// Unlike [`Position`], this trait doesn't get access to self,
85/// because the model might not be initialized when the widgets
86/// are updated in the factory.
87pub trait AsyncPosition<Pos> {
88    /// Returns the position.
89    ///
90    /// This function can be called very often
91    /// if widgets are moved a lot, so it should
92    /// be cheap to call.
93    fn position(index: usize) -> Pos;
94}
95
96impl<C> AsyncPosition<()> for C {
97    fn position(_index: usize) {}
98}