fractal/components/rows/
copyable_row.rs1use adw::{prelude::*, subclass::prelude::*};
2use gtk::{glib, CompositeTemplate};
3
4use crate::toast;
5
6#[derive(Debug, Default, Hash, Eq, PartialEq, Clone, Copy, glib::Enum)]
8#[repr(u32)]
9#[enum_type(name = "ActionRowMainTitle")]
10pub enum ActionRowMainTitle {
11 #[default]
13 Title = 0,
14 Subtitle = 1,
16}
17
18mod imp {
19 use std::{
20 cell::{Cell, RefCell},
21 marker::PhantomData,
22 };
23
24 use glib::subclass::InitializingObject;
25
26 use super::*;
27
28 #[derive(Debug, Default, CompositeTemplate, glib::Properties)]
29 #[template(resource = "/org/gnome/Fractal/ui/components/rows/copyable_row.ui")]
30 #[properties(wrapper_type = super::CopyableRow)]
31 pub struct CopyableRow {
32 #[template_child]
33 copy_button: TemplateChild<gtk::Button>,
34 #[template_child]
35 extra_suffix_bin: TemplateChild<adw::Bin>,
36 #[property(get = Self::copy_button_tooltip_text, set = Self::set_copy_button_tooltip_text, explicit_notify, nullable)]
38 copy_button_tooltip_text: PhantomData<Option<glib::GString>>,
39 #[property(get, set = Self::set_toast_text, explicit_notify, nullable)]
43 toast_text: RefCell<Option<String>>,
44 #[property(get, set = Self::set_main_title, explicit_notify, builder(ActionRowMainTitle::default()))]
50 main_title: Cell<ActionRowMainTitle>,
51 #[property(get = Self::extra_suffix, set = Self::set_extra_suffix, explicit_notify, nullable)]
55 extra_suffix: PhantomData<Option<gtk::Widget>>,
56 }
57
58 #[glib::object_subclass]
59 impl ObjectSubclass for CopyableRow {
60 const NAME: &'static str = "CopyableRow";
61 type Type = super::CopyableRow;
62 type ParentType = adw::ActionRow;
63
64 fn class_init(klass: &mut Self::Class) {
65 Self::bind_template(klass);
66
67 klass.install_action("copyable-row.copy", None, |obj, _, _| {
68 let imp = obj.imp();
69
70 let text = match imp.main_title.get() {
71 ActionRowMainTitle::Title => obj.title(),
72 ActionRowMainTitle::Subtitle => obj.subtitle().unwrap_or_default(),
73 };
74
75 obj.clipboard().set_text(&text);
76
77 if let Some(toast_text) = imp.toast_text.borrow().clone() {
78 toast!(obj, toast_text);
79 }
80 });
81 }
82
83 fn instance_init(obj: &InitializingObject<Self>) {
84 obj.init_template();
85 }
86 }
87
88 #[glib::derived_properties]
89 impl ObjectImpl for CopyableRow {}
90
91 impl WidgetImpl for CopyableRow {}
92 impl ListBoxRowImpl for CopyableRow {}
93 impl PreferencesRowImpl for CopyableRow {}
94 impl ActionRowImpl for CopyableRow {}
95
96 impl CopyableRow {
97 fn copy_button_tooltip_text(&self) -> Option<glib::GString> {
99 self.copy_button.tooltip_text()
100 }
101
102 fn set_copy_button_tooltip_text(&self, tooltip_text: Option<&str>) {
104 if self.copy_button_tooltip_text().as_deref() == tooltip_text {
105 return;
106 }
107
108 self.copy_button.set_tooltip_text(tooltip_text);
109 self.obj().notify_copy_button_tooltip_text();
110 }
111
112 fn set_toast_text(&self, text: Option<String>) {
114 if *self.toast_text.borrow() == text {
115 return;
116 }
117
118 self.toast_text.replace(text);
119 self.obj().notify_toast_text();
120 }
121
122 fn set_main_title(&self, main_title: ActionRowMainTitle) {
124 if self.main_title.get() == main_title {
125 return;
126 }
127 let obj = self.obj();
128
129 if main_title == ActionRowMainTitle::Title {
130 obj.remove_css_class("property");
131 } else {
132 obj.add_css_class("property");
133 }
134
135 self.main_title.set(main_title);
136 obj.notify_main_title();
137 }
138
139 fn extra_suffix(&self) -> Option<gtk::Widget> {
141 self.extra_suffix_bin.child()
142 }
143
144 fn set_extra_suffix(&self, widget: Option<>k::Widget>) {
146 if self.extra_suffix().as_ref() == widget {
147 return;
148 }
149
150 self.extra_suffix_bin.set_child(widget);
151 self.obj().notify_extra_suffix();
152 }
153 }
154}
155
156glib::wrapper! {
157 pub struct CopyableRow(ObjectSubclass<imp::CopyableRow>)
159 @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow,
160 @implements gtk::Actionable, gtk::Accessible;
161}
162
163impl CopyableRow {
164 pub fn new() -> Self {
165 glib::Object::new()
166 }
167}