[lab3] Edit panel (with actions)

This commit is contained in:
Andrew Golovashevich 2026-02-08 09:53:01 +03:00
parent 16444210e2
commit c0f03fd71a
5 changed files with 271 additions and 44 deletions

View File

@ -0,0 +1,109 @@
use std::ops::{Index, IndexMut};
enum Cell<T> {
Free { next_free_cell_id: Option<usize> },
Value { value: T },
}
pub(super) struct _PreserveIndexVec<T> {
next_free: Option<usize>,
buffer: Vec<Cell<T>>,
len: usize,
}
impl<T> _PreserveIndexVec<T> {
pub fn new() -> Self {
return Self {
next_free: None,
buffer: Vec::new(),
len: 0,
};
}
pub fn len(&self) -> usize {
return self.len;
}
pub fn add(&mut self, value: T) -> usize {
match self.next_free {
None => {
self.buffer.push(Cell::Value { value });
self.len += 1;
return self.buffer.len() - 1;
}
Some(i) => match self.buffer[i] {
Cell::Free { next_free_cell_id } => {
self.next_free = next_free_cell_id;
self.buffer[i] = Cell::Value { value };
self.len += 1;
return i;
}
Cell::Value { .. } => panic!("Busy cell marked as free"),
},
}
}
pub fn remove(&mut self, cell_index: usize) {
match self.buffer[cell_index] {
Cell::Free { .. } => panic!("Cell already free"),
Cell::Value { .. } => {
self.buffer[cell_index] = Cell::Free {
next_free_cell_id: self.next_free,
};
self.next_free = Some(cell_index);
self.len -= 1;
}
}
}
pub fn iter(&self) -> impl Iterator<Item=&T>{
return self.buffer.iter().filter_map(|c| {
match c {
Cell::Free { .. } => return None,
Cell::Value { value } => return Some(value)
}
})
}
pub fn iter_indexed(&self) -> impl Iterator<Item=(usize, &T)>{
return self.buffer.iter().enumerate().filter_map(|(i, c)| {
match c {
Cell::Free { .. } => return None,
Cell::Value { value } => return Some((i, value))
}
})
}
pub fn iter_indexed_mut(&mut self) -> impl Iterator<Item=(usize, &mut T)>{
return self.buffer.iter_mut().enumerate().filter_map(|(i, c)| {
match c {
Cell::Free { .. } => return None,
Cell::Value { value } => return Some((i, value))
}
})
}
}
impl<T> Index<usize> for _PreserveIndexVec<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
match self.buffer.get(index).expect("Cell index out of bounds") {
Cell::Free { .. } => panic!("Referenced cell doesn't exists"),
Cell::Value { value } => return value,
}
}
}
impl<T> IndexMut<usize> for _PreserveIndexVec<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match self
.buffer
.get_mut(index)
.expect("Cell index out of bounds")
{
Cell::Free { .. } => panic!("Referenced cell doesn't exists"),
Cell::Value { value } => return value,
}
}
}

View File

@ -1,3 +1,4 @@
use super::_PreserveIndexVec;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
pub struct Edge { pub struct Edge {
@ -7,43 +8,54 @@ pub struct Edge {
pub ferment_intensity: f64, pub ferment_intensity: f64,
} }
enum EdgeCell { impl Edge {
Free { next_free_cell_id: Option<usize> }, pub fn another(&self, current: usize) -> usize {
Value { data: Edge }, if self.vertex1_index == current {
return self.vertex2_index;
} else if self.vertex2_index == current {
return self.vertex1_index;
} else {
panic!("Edge not connected to specified vertex");
}
}
} }
pub struct EdgesVec { pub struct EdgesVec {
storage: Vec<EdgeCell>, data: _PreserveIndexVec<Edge>,
} }
impl EdgesVec { impl EdgesVec {
pub fn new() -> Self { pub fn new() -> Self {
return Self { return Self {
storage: Vec::new(), data: _PreserveIndexVec::new(),
}; };
} }
pub fn add(&mut self, vertex1: usize, vertex2: usize, length: f64) -> usize {
let data = Edge {
vertex1_index: vertex1,
vertex2_index: vertex2,
length,
ferment_intensity: 0.0,
};
return self.data.add(data);
}
pub fn remove(&mut self, edge_index: usize) {
self.data.remove(edge_index)
}
} }
impl Index<usize> for EdgesVec { impl Index<usize> for EdgesVec {
type Output = Edge; type Output = Edge;
fn index(&self, index: usize) -> &Self::Output { fn index(&self, index: usize) -> &Self::Output {
match self.storage.get(index).expect("Edge index out of bounds") { return self.data.index(index);
EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"),
EdgeCell::Value { data } => return data,
}
} }
} }
impl IndexMut<usize> for EdgesVec { impl IndexMut<usize> for EdgesVec {
fn index_mut(&mut self, index: usize) -> &mut Self::Output { fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match self return self.data.index_mut(index);
.storage
.get_mut(index)
.expect("Edge index out of bounds")
{
EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"),
EdgeCell::Value { data } => return data,
}
} }
} }

View File

@ -1,7 +1,12 @@
mod edges; mod edges;
mod state; mod state;
mod vertices;
mod _preserve_index_vec;
pub use edges::EdgesVec; pub use edges::EdgesVec;
pub use vertices::VerticesVec;
use _preserve_index_vec::_PreserveIndexVec;
pub struct AntsSimulationConfig { pub struct AntsSimulationConfig {
pub ferment_weight: f64, pub ferment_weight: f64,

50
lab3/src/algo/vertices.rs Normal file
View File

@ -0,0 +1,50 @@
use super::_PreserveIndexVec;
use std::collections::HashSet;
use std::ops::{Index, IndexMut};
pub struct VerticesVec {
data: _PreserveIndexVec<HashSet<usize>>,
}
impl VerticesVec {
pub fn new() -> Self {
return Self {
data: _PreserveIndexVec::new(),
};
}
pub fn len(&self) -> usize {
return self.data.len();
}
pub fn add(&mut self, edges: HashSet<usize>) -> usize {
return self.data.add(edges);
}
pub fn remove(&mut self, edge_index: usize) {
self.data.remove(edge_index)
}
pub fn iter(&self) -> impl Iterator<Item = &HashSet<usize>> {
return self.data.iter();
}
pub fn iter_indexed(&self) -> impl Iterator<Item = (usize, &HashSet<usize>)> {
return self.data.iter_indexed();
}
pub fn iter_indexed_mut(&mut self) -> impl Iterator<Item = (usize, &mut HashSet<usize>)> {
return self.data.iter_indexed_mut();
}
}
impl Index<usize> for VerticesVec {
type Output = HashSet<usize>;
fn index(&self, index: usize) -> &Self::Output {
return self.data.index(index);
}
}
impl IndexMut<usize> for VerticesVec {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
return self.data.index_mut(index);
}
}

View File

@ -2,13 +2,13 @@
mod algo; mod algo;
use crate::algo::{AntsSimulationConfig, EdgesVec}; use crate::algo::{AntsSimulationConfig, EdgesVec, VerticesVec};
use eframe::egui; use eframe::egui;
use eframe::egui::scroll_area::ScrollBarVisibility; use eframe::egui::scroll_area::ScrollBarVisibility;
use eframe::egui::{ScrollArea, Ui}; use eframe::egui::{ScrollArea, Ui};
use eframe::emath::Numeric; use eframe::emath::Numeric;
use egui_extras::{Column, TableBuilder}; use egui_extras::{Column, TableBuilder};
use std::collections::HashSet; use std::collections::{HashMap, HashSet};
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use std::ptr; use std::ptr;
use std::ptr::{NonNull, fn_addr_eq}; use std::ptr::{NonNull, fn_addr_eq};
@ -44,7 +44,7 @@ enum GlobalState {
struct MyApp { struct MyApp {
edges: EdgesVec, edges: EdgesVec,
vertices: Vec<HashSet<usize>>, vertices: VerticesVec,
config: AntsSimulationConfig, config: AntsSimulationConfig,
vertex_update: UpdatePending, vertex_update: UpdatePending,
speed: u32, speed: u32,
@ -55,7 +55,7 @@ impl Default for MyApp {
fn default() -> Self { fn default() -> Self {
return Self { return Self {
edges: EdgesVec::new(), edges: EdgesVec::new(),
vertices: Vec::new(), vertices: VerticesVec::new(),
vertex_update: UpdatePending::NoChange, vertex_update: UpdatePending::NoChange,
speed: 1, speed: 1,
config: AntsSimulationConfig { config: AntsSimulationConfig {
@ -90,6 +90,38 @@ fn _slider<T: Numeric>(
impl eframe::App for MyApp { impl eframe::App for MyApp {
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ui, |ui| { egui::CentralPanel::default().show(ui, |ui| {
match self.state {
GlobalState::Edit {} => match self.vertex_update {
UpdatePending::NoChange => {}
UpdatePending::Add => {
let new_vi = self.vertices.add(HashSet::new());
let mut newEdgesSet = HashSet::new();
for (vi, v) in self.vertices.iter_indexed_mut() {
if (vi == new_vi) {
continue;
}
let ei = self.edges.add(new_vi, vi, 1.0);
newEdgesSet.insert(ei);
v.insert(ei);
}
self.vertices[new_vi] = newEdgesSet;
self.vertex_update = UpdatePending::NoChange;
}
UpdatePending::Remove(vi) => {
let mut eis = Vec::with_capacity(self.vertices[vi].len());
for ei in self.vertices[vi].iter() {
eis.push(*ei)
}
for ei in eis {
self.vertices[self.edges[ei].another(vi)].remove(&ei);
self.edges.remove(ei);
}
self.vertices.remove(vi);
self.vertex_update = UpdatePending::NoChange;
}
},
GlobalState::Running { .. } => {}
}
edit_panel(self, ui) edit_panel(self, ui)
}); });
} }
@ -133,8 +165,12 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
.striped(true) // Alternating row colors .striped(true) // Alternating row colors
.resizable(true) .resizable(true)
.vscroll(false) .vscroll(false)
.column(Column::remainder())
.columns(Column::remainder(), data.vertices.len()) .columns(Column::remainder(), data.vertices.len())
.header(20.0, |mut header| { .header(20.0, |mut header| {
header.col(|ui| {
ui.label("#");
});
for (i, _) in data.vertices.iter().enumerate() { for (i, _) in data.vertices.iter().enumerate() {
header.col(|ui| { header.col(|ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
@ -146,31 +182,46 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
}); });
} }
}) })
.body(|body| { .body(|mut body| {
body.rows(20.0, data.vertices.len(), |mut row| { for (ri, (vi, v)) in data.vertices.iter_indexed().enumerate() {
let vi = row.index(); body.row(20.0, |mut row| {
let mut edges = row.col(|ui| {
Vec::<(usize, NonNull<f64>)>::with_capacity(data.vertices[vi].len()); ui.horizontal(|ui| {
for ei in data.vertices[vi].iter() { ui.label(ri.to_string());
let e = &mut data.edges[*ei]; if ui.button("-").clicked() {
let p; data.vertex_update = UpdatePending::Remove(vi);
if vi == e.vertex1_index {
p = (e.vertex2_index, &mut e.length);
} else {
p = (e.vertex1_index, &mut e.length);
} }
});
});
let mut edges = Vec::<(usize, NonNull<f64>)>::with_capacity(v.len());
for ei in v.iter() {
let e = &mut data.edges[*ei];
let p = (e.another(vi), &mut e.length);
edges.push((p.0, NonNull::from_mut(p.1))); edges.push((p.0, NonNull::from_mut(p.1)));
} }
edges.sort_by_key(|(k, _)| *k); edges.sort_by_key(|(k, _)| *k);
for (_, mut v) in edges {
let mut ci = 0usize;
for &(_, mut l) in edges.iter() {
if (ci == ri) {
row.col(|ui| {});
ci += 1
}
row.col(|ui| { row.col(|ui| {
ui.add( ui.add(
egui::Slider::new(unsafe { v.as_mut() }, 0.0..=10.0) egui::Slider::new(unsafe { l.as_mut() }, 0.0..=10.0)
.step_by(0.1), .step_by(0.1),
); );
}); });
ci += 1;
}
if ri == data.vertices.len() - 1 {
row.col(|ui| {});
}
});
} }
})
}); });
}); });
} }