diff --git a/lab2/src/algo/bit_vector.rs b/lab2/src/algo/bit_vector.rs index 228d16d..b892a0e 100644 --- a/lab2/src/algo/bit_vector.rs +++ b/lab2/src/algo/bit_vector.rs @@ -1,3 +1,4 @@ +use bgtu_ai_utility::{UpdatePending, UpdateTarget}; use std::cmp::min; use std::fmt::{Debug, Formatter}; use std::ops::{BitAnd, BitAndAssign, Index, IndexMut}; @@ -111,3 +112,21 @@ impl Debug for BitVector { return Ok(()); } } + +impl UpdateTarget for BitVector { + type Elem = bool; + + fn add(&mut self, value: bool) { + let i = self.len(); + *self = self.resized(i + 1); + self[i] = value + } + + fn remove(&mut self, index: usize) { + let mut new = self.resized(self.len() - 1); + for j in index..new.len() { + new[j] = self[j + 1] + } + *self = new; + } +} diff --git a/lab2/src/main.rs b/lab2/src/main.rs index dac1264..114612a 100644 --- a/lab2/src/main.rs +++ b/lab2/src/main.rs @@ -6,7 +6,7 @@ use crate::algo::BitVector; use bgtu_ai_utility::gui::{boot_eframe, labeled_slider}; use eframe::egui; use egui_extras::{Column, TableBuilder}; -use bgtu_ai_utility::UpdatePending; +use bgtu_ai_utility::{UpdatePending, UpdateTarget}; fn main() -> eframe::Result { return boot_eframe(|| MyApp::new()); @@ -41,45 +41,15 @@ impl MyApp { impl eframe::App for MyApp { fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) { - match self.columnUpdate { - UpdatePending::NoChange => {} - UpdatePending::Add => { - self.data = self - .data - .iter() - .map(|oldVec| oldVec.resized(oldVec.len() + 1)) - .collect(); - self.bitCount += 1; - self.columnUpdate = UpdatePending::NoChange; - } - UpdatePending::Remove(i) => { - self.data = self - .data - .iter() - .map(|oldVec| { - let mut newVec = oldVec.resized(oldVec.len() - 1); - for j in i..newVec.len() { - newVec[j] = oldVec[j + 1] - } - return newVec; - }) - .collect(); + self.columnUpdate.apply_many_and_clear( + self.data.iter_mut(), + || false + ); - self.bitCount -= 1; - self.columnUpdate = UpdatePending::NoChange; - } - } - match self.rowUpdate { - UpdatePending::NoChange => {} - UpdatePending::Add => { - self.data.push(BitVector::alloc(self.bitCount)); - self.rowUpdate = UpdatePending::NoChange; - } - UpdatePending::Remove(i) => { - self.data.remove(i); - self.rowUpdate = UpdatePending::NoChange; - } - } + self.rowUpdate.apply_and_clear( + &mut self.data, + || BitVector::alloc(self.bitCount) + ); egui::CentralPanel::default().show(ui, |ui| { ui.add_enabled_ui(matches!(self.result, None), |ui| { diff --git a/utility/src/lib.rs b/utility/src/lib.rs index 2395939..e680279 100644 --- a/utility/src/lib.rs +++ b/utility/src/lib.rs @@ -2,4 +2,4 @@ pub mod graph; pub mod gui; mod update_pending; -pub use update_pending::UpdatePending; \ No newline at end of file +pub use update_pending::{UpdatePending, UpdateTarget}; \ No newline at end of file diff --git a/utility/src/update_pending.rs b/utility/src/update_pending.rs index 1e836a9..830a497 100644 --- a/utility/src/update_pending.rs +++ b/utility/src/update_pending.rs @@ -2,4 +2,64 @@ pub enum UpdatePending { NoChange, Add, Remove(usize), +} + +impl UpdatePending { + pub fn apply(&self, target: &mut C, constructor: impl FnOnce() -> C::Elem) { + match self { + UpdatePending::NoChange => {} + UpdatePending::Add => target.add(constructor()), + UpdatePending::Remove(i) => target.remove(*i), + } + } + + pub fn apply_and_clear( + &mut self, + target: &mut C, + constructor: impl FnOnce() -> C::Elem, + ) { + match self { + UpdatePending::NoChange => return, + UpdatePending::Add => target.add(constructor()), + UpdatePending::Remove(i) => target.remove(*i), + } + *self = UpdatePending::NoChange; + } + + pub fn apply_many<'c, C: UpdateTarget + 'c>( + &self, + it: impl Iterator, + constructor: impl Fn() -> C::Elem, + ) { + for e in it { + self.apply(e, || constructor()) + } + } + pub fn apply_many_and_clear<'c, C: UpdateTarget + 'c>( + &mut self, + it: impl Iterator, + constructor: impl Fn() -> C::Elem, + ) { + self.apply_many(it, constructor); + *self = UpdatePending::NoChange; + } +} + +pub trait UpdateTarget { + type Elem; + + fn add(&mut self, value: Self::Elem); + fn remove(&mut self, index: usize); +} + +impl UpdateTarget for Vec { + type Elem = T; + + fn add(&mut self, value: Self::Elem) { + self.push(value); + } + + fn remove(&mut self, index: usize) { + Vec::remove(self, index); + } } \ No newline at end of file