use crate::model::marker::{MarkerId, MarkerList};
use fresh_core::overlay::OverlayNamespace;
#[derive(Debug, Clone)]
pub struct SoftBreakPoint {
pub namespace: OverlayNamespace,
pub marker_id: MarkerId,
pub indent: u16,
}
impl SoftBreakPoint {
pub fn position(&self, marker_list: &MarkerList) -> usize {
marker_list.get_position(self.marker_id).unwrap_or(0)
}
pub fn in_range(&self, start: usize, end: usize, marker_list: &MarkerList) -> bool {
let pos = self.position(marker_list);
pos >= start && pos < end
}
}
#[derive(Debug, Clone)]
pub struct SoftBreakManager {
breaks: Vec<SoftBreakPoint>,
}
impl SoftBreakManager {
pub fn new() -> Self {
Self { breaks: Vec::new() }
}
pub fn add(
&mut self,
marker_list: &mut MarkerList,
namespace: OverlayNamespace,
position: usize,
indent: u16,
) {
let marker_id = marker_list.create(position, false);
self.breaks.push(SoftBreakPoint {
namespace,
marker_id,
indent,
});
}
pub fn clear_namespace(&mut self, namespace: &OverlayNamespace, marker_list: &mut MarkerList) {
let markers_to_delete: Vec<_> = self
.breaks
.iter()
.filter(|b| &b.namespace == namespace)
.map(|b| b.marker_id)
.collect();
self.breaks.retain(|b| &b.namespace != namespace);
for marker_id in markers_to_delete {
marker_list.delete(marker_id);
}
}
pub fn remove_in_range(&mut self, start: usize, end: usize, marker_list: &mut MarkerList) {
let markers_to_delete: Vec<_> = self
.breaks
.iter()
.filter(|b| b.in_range(start, end, marker_list))
.map(|b| b.marker_id)
.collect();
self.breaks.retain(|b| !b.in_range(start, end, marker_list));
for marker_id in markers_to_delete {
marker_list.delete(marker_id);
}
}
pub fn clear(&mut self, marker_list: &mut MarkerList) {
for bp in &self.breaks {
marker_list.delete(bp.marker_id);
}
self.breaks.clear();
}
pub fn query_viewport(
&self,
start: usize,
end: usize,
marker_list: &MarkerList,
) -> Vec<(usize, u16)> {
let mut results: Vec<(usize, u16)> = self
.breaks
.iter()
.filter_map(|b| {
let pos = b.position(marker_list);
if pos >= start && pos < end {
Some((pos, b.indent))
} else {
None
}
})
.collect();
results.sort_by_key(|(pos, _)| *pos);
results
}
pub fn is_empty(&self) -> bool {
self.breaks.is_empty()
}
}
impl Default for SoftBreakManager {
fn default() -> Self {
Self::new()
}
}