fractal/session/view/content/room_history/message_row/
caption.rs1use gtk::{glib, prelude::*, subclass::prelude::*};
2use ruma::events::room::message::FormattedBody;
3
4use super::{text::MessageText, ContentFormat};
5use crate::{prelude::*, session::model::Room};
6
7mod imp {
8 use std::marker::PhantomData;
9
10 use super::*;
11
12 #[derive(Debug, Default, glib::Properties)]
13 #[properties(wrapper_type = super::MessageCaption)]
14 pub struct MessageCaption {
15 #[property(get = Self::child, set = Self::set_child, explicit_notify, nullable)]
17 child: PhantomData<Option<gtk::Widget>>,
18 caption_widget: MessageText,
19 }
20
21 #[glib::object_subclass]
22 impl ObjectSubclass for MessageCaption {
23 const NAME: &'static str = "ContentMessageCaption";
24 type Type = super::MessageCaption;
25 type ParentType = gtk::Grid;
26
27 fn class_init(klass: &mut Self::Class) {
28 klass.set_css_name("message-caption");
29
30 klass.set_accessible_role(gtk::AccessibleRole::Group);
31 }
32 }
33
34 #[glib::derived_properties]
35 impl ObjectImpl for MessageCaption {
36 fn constructed(&self) {
37 self.parent_constructed();
38
39 let obj = self.obj();
40 obj.attach(&self.caption_widget, 0, 1, 1, 1);
41 obj.set_row_spacing(6);
42 }
43 }
44
45 impl WidgetImpl for MessageCaption {}
46 impl GridImpl for MessageCaption {}
47
48 impl MessageCaption {
49 fn child(&self) -> Option<gtk::Widget> {
51 self.obj().child_at(0, 0)
52 }
53
54 fn set_child(&self, widget: Option<gtk::Widget>) {
56 let prev_widget = self.child();
57
58 if prev_widget == widget {
59 return;
60 }
61 let obj = self.obj();
62
63 if let Some(widget) = prev_widget {
64 obj.remove(&widget);
65 }
66
67 if let Some(widget) = widget {
68 obj.attach(&widget, 0, 0, 1, 1);
69 }
70
71 obj.notify_child();
72 }
73
74 pub(super) fn set_caption(
76 &self,
77 caption: String,
78 formatted_caption: Option<FormattedBody>,
79 room: &Room,
80 format: ContentFormat,
81 detect_at_room: bool,
82 ) {
83 self.caption_widget.with_markup(
84 formatted_caption,
85 caption,
86 room,
87 format,
88 detect_at_room,
89 );
90 }
91 }
92}
93
94glib::wrapper! {
95 pub struct MessageCaption(ObjectSubclass<imp::MessageCaption>)
97 @extends gtk::Widget, gtk::Grid, @implements gtk::Accessible;
98}
99
100impl MessageCaption {
101 pub fn new() -> Self {
102 glib::Object::new()
103 }
104
105 pub(crate) fn set_caption(
107 &self,
108 caption: String,
109 formatted_caption: Option<FormattedBody>,
110 room: &Room,
111 format: ContentFormat,
112 detect_at_room: bool,
113 ) {
114 self.imp()
115 .set_caption(caption, formatted_caption, room, format, detect_at_room);
116 }
117}
118
119impl Default for MessageCaption {
120 fn default() -> Self {
121 Self::new()
122 }
123}
124
125impl ChildPropertyExt for MessageCaption {
126 fn child_property(&self) -> Option<gtk::Widget> {
127 self.child()
128 }
129
130 fn set_child_property(&self, child: Option<&impl IsA<gtk::Widget>>) {
131 self.set_child(child.map(Cast::upcast_ref));
132 }
133}