added new Client
, Entry
, ClientStore
structs and related logic
This commit is contained in:
parent
e924e8efc0
commit
db94c82185
358
src/clients2.rs
Normal file
358
src/clients2.rs
Normal file
|
@ -0,0 +1,358 @@
|
|||
#![allow(dead_code)]
|
||||
use std::{borrow::Borrow, hash::Hash};
|
||||
|
||||
/// Client structure.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Client<T> {
|
||||
window_id: T,
|
||||
size: (i32, i32),
|
||||
position: (i32, i32),
|
||||
transient_for: Option<T>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum Entry<T> {
|
||||
Tiled(T),
|
||||
Floating(T),
|
||||
Transient(T),
|
||||
Fullscreen(T),
|
||||
Vacant,
|
||||
}
|
||||
|
||||
type ClientSet<T> = indexmap::IndexMap<T, Client<T>>;
|
||||
//type ClientSet<T> = std::collections::HashMap<T, Client<T>>;
|
||||
|
||||
struct ClientStore<T>
|
||||
where
|
||||
T: Hash + Eq,
|
||||
{
|
||||
tiled_clients: ClientSet<T>,
|
||||
floating_clients: ClientSet<T>,
|
||||
transient_clients: ClientSet<T>,
|
||||
fullscreen_clients: ClientSet<T>,
|
||||
}
|
||||
|
||||
impl<T> PartialEq for Client<T>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.window_id == other.window_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for Client<T> where T: Eq {}
|
||||
|
||||
impl<T> PartialOrd for Client<T>
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.window_id.partial_cmp(&other.window_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Ord for Client<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.window_id.cmp(&other.window_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Hash for Client<T>
|
||||
where
|
||||
T: Hash,
|
||||
{
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.window_id.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Borrow<T> for Client<T> {
|
||||
fn borrow(&self) -> &T {
|
||||
&self.window_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Client<T> {
|
||||
pub fn new(window_id: T) -> Self {
|
||||
Self {
|
||||
window_id,
|
||||
size: (100, 100),
|
||||
position: (0, 0),
|
||||
transient_for: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_id_ref(&self) -> &T {
|
||||
&self.window_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Client<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
pub fn window_id(&self) -> T {
|
||||
self.window_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Entry<T>> for Option<T> {
|
||||
fn from(entry: Entry<T>) -> Self {
|
||||
match entry {
|
||||
Entry::Floating(c)
|
||||
| Entry::Tiled(c)
|
||||
| Entry::Fullscreen(c)
|
||||
| Entry::Transient(c) => Some(c),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> From<&'a Entry<T>> for Option<&'a T> {
|
||||
fn from(entry: &'a Entry<T>) -> Self {
|
||||
match entry {
|
||||
Entry::Floating(c)
|
||||
| Entry::Tiled(c)
|
||||
| Entry::Fullscreen(c)
|
||||
| Entry::Transient(c) => Some(c),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> From<&'a mut Entry<T>> for Option<&'a mut T> {
|
||||
fn from(entry: &'a mut Entry<T>) -> Self {
|
||||
match entry {
|
||||
Entry::Floating(c)
|
||||
| Entry::Tiled(c)
|
||||
| Entry::Fullscreen(c)
|
||||
| Entry::Transient(c) => Some(c),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<Entry<T>>> for Entry<T> {
|
||||
fn from(opt: Option<Entry<T>>) -> Self {
|
||||
match opt {
|
||||
Some(entry) => entry,
|
||||
None => Entry::Vacant,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Entry<T> {
|
||||
fn unwrap(self) -> T {
|
||||
Option::<T>::from(self).unwrap()
|
||||
}
|
||||
|
||||
fn unwrap_ref(&self) -> &T {
|
||||
Option::<&T>::from(self).unwrap()
|
||||
}
|
||||
|
||||
fn unwrap_mut(&mut self) -> &mut T {
|
||||
Option::<&mut T>::from(self).unwrap()
|
||||
}
|
||||
|
||||
fn is_floating(&self) -> bool {
|
||||
match self {
|
||||
Self::Floating(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_tiled(&self) -> bool {
|
||||
match self {
|
||||
Self::Tiled(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_transient(&self) -> bool {
|
||||
match self {
|
||||
Self::Transient(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_fullscreen(&self) -> bool {
|
||||
match self {
|
||||
Self::Fullscreen(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for ClientStore<T>
|
||||
where
|
||||
T: Hash + Eq,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
tiled_clients: Default::default(),
|
||||
floating_clients: Default::default(),
|
||||
transient_clients: Default::default(),
|
||||
fullscreen_clients: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ClientStore<T>
|
||||
where
|
||||
T: Hash + Eq + Copy,
|
||||
{
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn insert(&mut self, entry: Entry<Client<T>>) -> Entry<&Client<T>> {
|
||||
if let Some(key) =
|
||||
Option::<&Client<T>>::from(&entry).map(|c| c.window_id())
|
||||
{
|
||||
match entry {
|
||||
Entry::Floating(client) => {
|
||||
self.floating_clients.insert(key, client);
|
||||
}
|
||||
Entry::Tiled(client) => {
|
||||
self.tiled_clients.insert(key, client);
|
||||
}
|
||||
Entry::Transient(client) => {
|
||||
self.transient_clients.insert(key, client);
|
||||
}
|
||||
Entry::Fullscreen(client) => {
|
||||
self.fullscreen_clients.insert(key, client);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
self.get(&key).into()
|
||||
} else {
|
||||
Entry::Vacant
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(&mut self, key: &T) -> Entry<Client<T>> {
|
||||
if let Some(client) = self.tiled_clients.remove(key) {
|
||||
Entry::Tiled(client)
|
||||
} else if let Some(client) = self.floating_clients.remove(key) {
|
||||
Entry::Floating(client)
|
||||
} else if let Some(client) = self.transient_clients.remove(key) {
|
||||
Entry::Transient(client)
|
||||
} else if let Some(client) = self.fullscreen_clients.remove(key) {
|
||||
Entry::Fullscreen(client)
|
||||
} else {
|
||||
Entry::Vacant
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, key: &T) -> Entry<&Client<T>> {
|
||||
if let Some(client) = self.tiled_clients.get(key) {
|
||||
Entry::Tiled(client)
|
||||
} else if let Some(client) = self.floating_clients.get(key) {
|
||||
Entry::Floating(client)
|
||||
} else if let Some(client) = self.transient_clients.get(key) {
|
||||
Entry::Transient(client)
|
||||
} else if let Some(client) = self.fullscreen_clients.get(key) {
|
||||
Entry::Fullscreen(client)
|
||||
} else {
|
||||
Entry::Vacant
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, key: &T) -> Entry<&mut Client<T>> {
|
||||
if let Some(client) = self.tiled_clients.get_mut(key) {
|
||||
Entry::Tiled(client)
|
||||
} else if let Some(client) = self.floating_clients.get_mut(key) {
|
||||
Entry::Floating(client)
|
||||
} else if let Some(client) = self.transient_clients.get_mut(key) {
|
||||
Entry::Transient(client)
|
||||
} else if let Some(client) = self.fullscreen_clients.get_mut(key) {
|
||||
Entry::Fullscreen(client)
|
||||
} else {
|
||||
Entry::Vacant
|
||||
}
|
||||
}
|
||||
|
||||
fn contains(&self, key: &T) -> bool {
|
||||
self.tiled_clients.contains_key(key)
|
||||
|| self.floating_clients.contains_key(key)
|
||||
|| self.transient_clients.contains_key(key)
|
||||
|| self.fullscreen_clients.contains_key(key)
|
||||
}
|
||||
|
||||
fn iter_tiled(&self) -> impl Iterator<Item = (&T, &Client<T>)> {
|
||||
self.tiled_clients.iter()
|
||||
}
|
||||
|
||||
fn iter_mut_tiled(&mut self) -> impl Iterator<Item = (&T, &mut Client<T>)> {
|
||||
self.tiled_clients.iter_mut()
|
||||
}
|
||||
|
||||
fn iter_floating(&self) -> impl Iterator<Item = (&T, &Client<T>)> {
|
||||
self.floating_clients.iter()
|
||||
}
|
||||
|
||||
fn iter_mut_floating(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = (&T, &mut Client<T>)> {
|
||||
self.floating_clients.iter_mut()
|
||||
}
|
||||
|
||||
fn iter_transient(&self) -> impl Iterator<Item = (&T, &Client<T>)> {
|
||||
self.transient_clients.iter()
|
||||
}
|
||||
|
||||
fn iter_mut_transient(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = (&T, &mut Client<T>)> {
|
||||
self.transient_clients.iter_mut()
|
||||
}
|
||||
|
||||
fn iter_fullscreen(&self) -> impl Iterator<Item = (&T, &Client<T>)> {
|
||||
self.fullscreen_clients.iter()
|
||||
}
|
||||
|
||||
fn iter_mut_fullscreen(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = (&T, &mut Client<T>)> {
|
||||
self.fullscreen_clients.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn clientstore_insert_contain() {
|
||||
let client = Client::new(1u64);
|
||||
|
||||
let mut client_store = ClientStore::new();
|
||||
client_store.insert(Entry::Tiled(client.clone()));
|
||||
|
||||
assert!(client_store.contains(client.borrow()));
|
||||
assert!(client_store.contains(&1));
|
||||
|
||||
let client2 = Client::new(3u64);
|
||||
client_store.insert(Entry::Floating(client2.clone()));
|
||||
|
||||
assert!(client_store.contains(&client.borrow()));
|
||||
assert!(client_store.contains(&1));
|
||||
|
||||
assert!(client_store.contains(&client2.borrow()));
|
||||
assert!(client_store.contains(&3));
|
||||
|
||||
assert_eq!(
|
||||
Entry::Tiled(client.clone()),
|
||||
client_store.remove(&client.borrow())
|
||||
);
|
||||
assert_eq!(Entry::Vacant, client_store.remove(&client.borrow()));
|
||||
assert_eq!(Entry::Vacant, client_store.remove(&1));
|
||||
|
||||
assert!(client_store.contains(&client2.borrow()));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue