use std::cell::Cell;
use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
use super::{Category, CategoryType, SidebarIconItem, SidebarIconItemType, SidebarItem};
use crate::session::model::{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)]
pub room_list: OnceCell<RoomList>,
#[property(get, construct_only)]
pub verification_list: OnceCell<VerificationList>,
#[property(get, set = Self::set_show_all_for_category, explicit_notify, builder(CategoryType::default()))]
pub show_all_for_category: Cell<CategoryType>,
}
#[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(Category::new(
CategoryType::VerificationRequest,
&verification_list,
)),
SidebarItem::new(Category::new(CategoryType::Invited, &room_list)),
SidebarItem::new(Category::new(CategoryType::Favorite, &room_list)),
SidebarItem::new(Category::new(CategoryType::Normal, &room_list)),
SidebarItem::new(Category::new(CategoryType::LowPriority, &room_list)),
SidebarItem::new(Category::new(CategoryType::Left, &room_list)),
SidebarItem::new(SidebarIconItem::new(SidebarIconItemType::Forget)),
]
});
for item in list {
if let Some(category) = item.inner_item().downcast_ref::<Category>() {
category.connect_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 {
fn list(&self) -> &[SidebarItem; TOP_LEVEL_ITEMS_COUNT] {
self.list.get().unwrap()
}
fn set_show_all_for_category(&self, category: CategoryType) {
if category == self.show_all_for_category.get() {
return;
}
self.show_all_for_category.set(category);
for item in self.list() {
self.update_item_visibility(item);
}
self.obj().notify_show_all_for_category();
}
fn update_item_visibility(&self, item: &SidebarItem) {
item.update_visibility_for_category(self.show_all_for_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 inhibit_expanded(&self, inhibit: bool) {
self.imp().inhibit_expanded(inhibit);
}
}