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