fractal/session/model/sidebar_data/
item_list.rsuse std::cell::Cell;
use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
use super::{
SidebarIconItem, SidebarIconItemType, SidebarItem, SidebarSection, SidebarSectionName,
};
use crate::session::model::{RoomCategory, RoomList, VerificationList};
const TOP_LEVEL_ITEMS_COUNT: usize = 8;
mod imp {
use std::cell::OnceCell;
use super::*;
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::SidebarItemList)]
pub struct SidebarItemList {
list: OnceCell<[SidebarItem; TOP_LEVEL_ITEMS_COUNT]>,
#[property(get, construct_only)]
room_list: OnceCell<RoomList>,
#[property(get, construct_only)]
verification_list: OnceCell<VerificationList>,
show_all_for_room_category: Cell<Option<RoomCategory>>,
}
#[glib::object_subclass]
impl ObjectSubclass for SidebarItemList {
const NAME: &'static str = "SidebarItemList";
type Type = super::SidebarItemList;
type Interfaces = (gio::ListModel,);
}
#[glib::derived_properties]
impl ObjectImpl for SidebarItemList {
fn constructed(&self) {
self.parent_constructed();
let obj = self.obj();
let room_list = obj.room_list();
let verification_list = obj.verification_list();
let list = self.list.get_or_init(|| {
[
SidebarItem::new(SidebarIconItem::new(SidebarIconItemType::Explore)),
SidebarItem::new(SidebarSection::new(
SidebarSectionName::VerificationRequest,
&verification_list,
)),
SidebarItem::new(SidebarSection::new(SidebarSectionName::Invited, &room_list)),
SidebarItem::new(SidebarSection::new(
SidebarSectionName::Favorite,
&room_list,
)),
SidebarItem::new(SidebarSection::new(SidebarSectionName::Normal, &room_list)),
SidebarItem::new(SidebarSection::new(
SidebarSectionName::LowPriority,
&room_list,
)),
SidebarItem::new(SidebarSection::new(SidebarSectionName::Left, &room_list)),
SidebarItem::new(SidebarIconItem::new(SidebarIconItemType::Forget)),
]
});
for item in list {
if let Some(section) = item.inner_item().downcast_ref::<SidebarSection>() {
section.connect_is_empty_notify(clone!(
#[weak(rename_to = imp)]
self,
#[weak]
item,
move |_| {
imp.update_item_visibility(&item);
}
));
}
self.update_item_visibility(item);
}
}
}
impl ListModelImpl for SidebarItemList {
fn item_type(&self) -> glib::Type {
SidebarItem::static_type()
}
fn n_items(&self) -> u32 {
TOP_LEVEL_ITEMS_COUNT as u32
}
fn item(&self, position: u32) -> Option<glib::Object> {
self.list().get(position as usize).cloned().and_upcast()
}
}
impl SidebarItemList {
pub(super) fn list(&self) -> &[SidebarItem; TOP_LEVEL_ITEMS_COUNT] {
self.list.get().unwrap()
}
pub(super) fn set_show_all_for_room_category(&self, category: Option<RoomCategory>) {
if self.show_all_for_room_category.get() == category {
return;
}
self.show_all_for_room_category.set(category);
for item in self.list() {
self.update_item_visibility(item);
}
}
fn update_item_visibility(&self, item: &SidebarItem) {
item.update_visibility_for_room_category(self.show_all_for_room_category.get());
}
pub(super) fn inhibit_expanded(&self, inhibit: bool) {
for item in self.list() {
item.set_inhibit_expanded(inhibit);
}
}
}
}
glib::wrapper! {
pub struct SidebarItemList(ObjectSubclass<imp::SidebarItemList>)
@implements gio::ListModel;
}
impl SidebarItemList {
pub fn new(room_list: &RoomList, verification_list: &VerificationList) -> Self {
glib::Object::builder()
.property("room-list", room_list)
.property("verification-list", verification_list)
.build()
}
pub fn set_show_all_for_room_category(&self, category: Option<RoomCategory>) {
self.imp().set_show_all_for_room_category(category);
}
pub fn inhibit_expanded(&self, inhibit: bool) {
self.imp().inhibit_expanded(inhibit);
}
pub fn section_from_room_category(&self, category: RoomCategory) -> Option<SidebarSection> {
let index = match category {
RoomCategory::Invited => 2,
RoomCategory::Favorite => 3,
RoomCategory::Normal => 4,
RoomCategory::LowPriority => 5,
RoomCategory::Left => 6,
_ => return None,
};
self.imp()
.list()
.get(index)
.map(SidebarItem::inner_item)
.and_downcast()
}
}