use gpui::{Context, Pixels, px};
use markdown::{BlockKind, Form};
use crate::{editor::Editor, history::EditKind};
const MIN_HEIGHT: f32 = 120.0;
#[derive(Clone, Copy)]
pub(super) struct Sizing {
pub ix: usize,
from: Pixels,
start: Pixels,
pub live: Option<u32>,
}
fn stated(kind: &BlockKind) -> Option<Option<u32>> {
match kind {
BlockKind::Code { height, .. } => Some(*height),
BlockKind::Bookmark {
form: Form::Embed(height),
..
} => Some(*height),
_ => None,
}
}
impl Editor {
pub(super) fn held_height(&self) -> Option<(usize, u32)> {
let sizing = self.sizing?;
Some((sizing.ix, sizing.live?))
}
pub(super) fn drag_height(&mut self, y: Pixels, cx: &mut Context<Self>) -> bool {
let Some(sizing) = self.sizing.as_mut() else {
return false;
};
let height = (sizing.start + (y - sizing.from)).max(px(MIN_HEIGHT));
sizing.live = Some(height.as_f32().round() as u32);
cx.notify();
true
}
pub(super) fn drop_height(&mut self, cx: &mut Context<Self>) -> bool {
let Some(sizing) = self.sizing.take() else {
return false;
};
let Some(height) = sizing.live else {
cx.notify();
return true;
};
let current = self
.doc
.blocks
.get(sizing.ix)
.and_then(|block| stated(&block.kind));
if current != Some(Some(height)) {
self.edit(EditKind::Structure, cx, |this| {
match this
.doc
.blocks
.get_mut(sizing.ix)
.map(|block| &mut block.kind)
{
Some(BlockKind::Code { height: at, .. }) => *at = Some(height),
Some(BlockKind::Bookmark { form, .. }) => *form = Form::Embed(Some(height)),
_ => {}
}
vec![]
});
self.reveal = None;
} else {
cx.notify();
}
true
}
pub(super) fn start_height(&mut self, ix: usize, y: Pixels, cx: &mut Context<Self>) {
let Some(painted) = self.layouts.painted_bounds(ix) else {
return;
};
self.sizing = Some(Sizing {
ix,
from: y,
start: painted.size.height,
live: None,
});
cx.notify();
}
}