use std::collections::HashMap;
use gpui::{ElementId, Hsla, SharedString};
use super::{DiffLinePosition, DiffLineRange, DiffSide};
#[derive(Clone)]
pub struct DiffDecoration {
range: DiffLineRange,
background: Option<Hsla>,
}
impl DiffDecoration {
pub fn new(range: DiffLineRange) -> Self {
Self {
range,
background: None,
}
}
pub fn with_background(mut self, background: impl Into<Hsla>) -> Self {
self.background = Some(background.into());
self
}
pub fn range(&self) -> &DiffLineRange {
&self.range
}
pub fn background(&self) -> Option<Hsla> {
self.background
}
fn contains(&self, side: DiffSide, line: usize) -> bool {
let range = &self.range;
if range.is_single_side() {
side == range.side() && (range.start()..=range.end()).contains(&line)
} else if side == range.side() {
line >= range.start()
} else {
line <= range.end()
}
}
}
#[derive(Clone)]
pub struct DiffGutterMarker {
id: ElementId,
position: DiffLinePosition,
label: SharedString,
}
impl DiffGutterMarker {
pub fn new(id: impl Into<ElementId>, position: DiffLinePosition) -> Self {
Self {
id: id.into(),
position,
label: SharedString::default(),
}
}
pub fn with_label(mut self, label: impl Into<SharedString>) -> Self {
self.label = label.into();
self
}
pub fn id(&self) -> &ElementId {
&self.id
}
pub fn position(&self) -> &DiffLinePosition {
&self.position
}
pub fn label(&self) -> &SharedString {
&self.label
}
}
#[derive(Default)]
pub(super) struct Decorations {
files: HashMap<SharedString, Vec<DiffDecoration>>,
}
impl Decorations {
pub(super) fn new(decorations: impl IntoIterator<Item = DiffDecoration>) -> Self {
let mut index = Self::default();
for decoration in decorations {
index
.files
.entry(decoration.range.path().clone())
.or_default()
.push(decoration);
}
index
}
pub(super) fn at(&self, position: &DiffLinePosition) -> Option<&DiffDecoration> {
self.files
.get(position.path())?
.iter()
.rev()
.find(|decoration| decoration.contains(position.side(), position.line()))
}
}
#[derive(Default)]
pub(super) struct GutterMarkers {
lines: HashMap<DiffLinePosition, DiffGutterMarker>,
}
impl GutterMarkers {
pub(super) fn new(markers: impl IntoIterator<Item = DiffGutterMarker>) -> Self {
let mut index = Self::default();
for marker in markers {
index.lines.entry(marker.position.clone()).or_insert(marker);
}
index
}
pub(super) fn is_empty(&self) -> bool {
self.lines.is_empty()
}
pub(super) fn at(&self, position: &DiffLinePosition) -> Option<&DiffGutterMarker> {
self.lines.get(position)
}
}