fractal/session/view/sidebar/
section_row.rsuse adw::subclass::prelude::BinImpl;
use gettextrs::gettext;
use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use crate::session::model::{RoomCategory, SidebarSection, SidebarSectionName};
mod imp {
use std::{
cell::{Cell, RefCell},
marker::PhantomData,
};
use glib::subclass::InitializingObject;
use super::*;
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
#[template(resource = "/org/gnome/Fractal/ui/session/view/sidebar/section_row.ui")]
#[properties(wrapper_type = super::SidebarSectionRow)]
pub struct SidebarSectionRow {
#[property(get, set = Self::set_section, explicit_notify, nullable)]
section: RefCell<Option<SidebarSection>>,
section_binding: RefCell<Option<glib::Binding>>,
#[property(get, set = Self::set_is_expanded, explicit_notify, construct, default = true)]
is_expanded: Cell<bool>,
#[property(get = Self::label)]
label: PhantomData<Option<String>>,
show_label_for_room_category: Cell<Option<RoomCategory>>,
#[template_child]
pub(super) display_name: TemplateChild<gtk::Label>,
}
#[glib::object_subclass]
impl ObjectSubclass for SidebarSectionRow {
const NAME: &'static str = "SidebarSectionRow";
type Type = super::SidebarSectionRow;
type ParentType = adw::Bin;
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
klass.set_css_name("sidebar-section");
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for SidebarSectionRow {
fn constructed(&self) {
self.parent_constructed();
self.obj().connect_parent_notify(|obj| {
obj.set_expanded_accessibility_state(obj.is_expanded());
});
}
fn dispose(&self) {
if let Some(binding) = self.section_binding.take() {
binding.unbind();
}
}
}
impl WidgetImpl for SidebarSectionRow {}
impl BinImpl for SidebarSectionRow {}
impl SidebarSectionRow {
fn set_section(&self, section: Option<SidebarSection>) {
if *self.section.borrow() == section {
return;
}
if let Some(binding) = self.section_binding.take() {
binding.unbind();
}
let obj = self.obj();
if let Some(section) = §ion {
let section_binding = section
.bind_property("is-expanded", &*obj, "is-expanded")
.sync_create()
.build();
self.section_binding.replace(Some(section_binding));
}
self.section.replace(section);
obj.notify_section();
obj.notify_label();
}
fn label(&self) -> Option<String> {
let target_section_name = self.section.borrow().as_ref()?.name();
let source_room_category = self.show_label_for_room_category.get();
let label = match source_room_category {
Some(RoomCategory::Invited) => match target_section_name {
SidebarSectionName::Favorite => gettext("Join Room as Favorite"),
SidebarSectionName::Normal => gettext("Join Room"),
SidebarSectionName::LowPriority => gettext("Join Room as Low Priority"),
SidebarSectionName::Left => gettext("Reject Invite"),
_ => target_section_name.to_string(),
},
Some(RoomCategory::Favorite) => match target_section_name {
SidebarSectionName::Normal => gettext("Move to Rooms"),
SidebarSectionName::LowPriority => gettext("Move to Low Priority"),
SidebarSectionName::Left => gettext("Leave Room"),
_ => target_section_name.to_string(),
},
Some(RoomCategory::Normal) => match target_section_name {
SidebarSectionName::Favorite => gettext("Move to Favorites"),
SidebarSectionName::LowPriority => gettext("Move to Low Priority"),
SidebarSectionName::Left => gettext("Leave Room"),
_ => target_section_name.to_string(),
},
Some(RoomCategory::LowPriority) => match target_section_name {
SidebarSectionName::Favorite => gettext("Move to Favorites"),
SidebarSectionName::Normal => gettext("Move to Rooms"),
SidebarSectionName::Left => gettext("Leave Room"),
_ => target_section_name.to_string(),
},
Some(RoomCategory::Left) => match target_section_name {
SidebarSectionName::Favorite => gettext("Rejoin Room as Favorite"),
SidebarSectionName::Normal => gettext("Rejoin Room"),
SidebarSectionName::LowPriority => gettext("Rejoin Room as Low Priority"),
_ => target_section_name.to_string(),
},
_ => target_section_name.to_string(),
};
Some(label)
}
fn set_is_expanded(&self, is_expanded: bool) {
if self.is_expanded.get() == is_expanded {
return;
}
let obj = self.obj();
if is_expanded {
obj.set_state_flags(gtk::StateFlags::CHECKED, false);
} else {
obj.unset_state_flags(gtk::StateFlags::CHECKED);
}
self.is_expanded.set(is_expanded);
obj.set_expanded_accessibility_state(is_expanded);
obj.notify_is_expanded();
}
pub(super) fn set_show_label_for_room_category(&self, category: Option<RoomCategory>) {
if self.show_label_for_room_category.get() == category {
return;
}
self.show_label_for_room_category.set(category);
self.obj().notify_label();
}
}
}
glib::wrapper! {
pub struct SidebarSectionRow(ObjectSubclass<imp::SidebarSectionRow>)
@extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
}
impl SidebarSectionRow {
pub fn new() -> Self {
glib::Object::new()
}
pub fn set_show_label_for_room_category(&self, category: Option<RoomCategory>) {
self.imp().set_show_label_for_room_category(category);
}
fn set_expanded_accessibility_state(&self, is_expanded: bool) {
if let Some(row) = self.parent() {
row.update_state(&[gtk::accessible::State::Expanded(Some(is_expanded))]);
}
}
pub fn labelled_by(&self) -> >k::Accessible {
self.imp().display_name.upcast_ref()
}
}