1use super::*;
4
5impl Editor {
6 pub(super) fn checkbox_at(&self, at: gpui::Point<gpui::Pixels>) -> Option<usize> {
11 let ix = self.layouts.block_at(at)?;
12 self.layouts
13 .checkbox_bounds(ix)
14 .is_some_and(|bounds| bounds.contains(&at))
15 .then_some(ix)
16 }
17
18 pub(super) fn append_tail(&mut self, cx: &mut Context<Self>) -> bool {
23 let Some(last) = self.doc.blocks.len().checked_sub(1) else {
24 return false;
25 };
26 if !self.blocks() {
27 return false;
28 }
29 if self.doc.blocks[last].parts().last() == Some(&Part::Body) {
30 return false;
31 }
32 self.edit(EditKind::Structure, cx, |this| {
33 this.doc
34 .blocks
35 .push(markdown::Block::new(BlockKind::Paragraph(Text::default())));
36 let ix = this.doc.blocks.len() - 1;
37 this.selection = Selection::at(Cursor::new(ix, Part::Body, 0).clamp(&this.doc));
38 vec![]
39 });
40 true
41 }
42
43 pub fn press(
51 &mut self,
52 position: gpui::Point<gpui::Pixels>,
53 click_count: usize,
54 modifiers: gpui::Modifiers,
55 window: &mut Window,
56 cx: &mut Context<Self>,
57 ) {
58 if window.default_prevented() {
59 return;
60 }
61 window.prevent_default();
62 self.pressed(position, click_count, modifiers, window, cx);
63 }
64
65 pub(super) fn in_drag(&self) -> bool {
68 self.dragging.is_some()
69 || self.lifted.is_some()
70 || self.resizing.is_some()
71 || self.table_drag.is_some()
72 }
73
74 pub(super) fn drag_to(&mut self, position: gpui::Point<gpui::Pixels>, cx: &mut Context<Self>) {
76 if self.table_drag.is_some() {
77 return self.drag_table_to(position, cx);
78 }
79 if let Some((from, _)) = self.lifted {
81 if let Some(to) = self.layouts.block_at(position) {
82 self.lifted = Some((from, to));
83 cx.notify();
84 }
85 return;
86 }
87 if let Some((ix, _)) = self.resizing {
90 if let Some(width) = self.dragged_width(ix, position.x) {
91 self.resizing = Some((ix, Some(width)));
92 cx.notify();
93 }
94 return;
95 }
96 if let Some((unit, pressed)) = self.dragging.clone()
97 && let Some(hit) = self.layouts.hit(position)
98 {
99 let (anchor, head) = ui::input::drag_selection(pressed, hit.span(unit, &self.doc));
100 self.selection = Selection::new(anchor, head).clamp(&self.doc);
101 cx.notify();
102 }
103 }
104
105 pub(super) fn pressed(
106 &mut self,
107 position: gpui::Point<gpui::Pixels>,
108 click_count: usize,
109 modifiers: gpui::Modifiers,
110 window: &mut Window,
111 cx: &mut Context<Self>,
112 ) {
113 ui::popover::close_popup(self, cx, |this| &mut this.block_menu);
114 ui::popover::close_popup(self, cx, |this| &mut this.language_menu);
115 ui::popover::close_popup(self, cx, |this| &mut this.table_menu);
116 self.pasted = None;
117 self.focus_handle.clone().focus(window, cx);
118 if let Some(ix) = self.checkbox_at(position) {
122 self.toggle_task(ix, cx);
123 return;
124 }
125 if self.tail_click(position, cx) {
126 return;
127 }
128 let Some(hit) = self.layouts.hit(position) else {
129 return cx.notify();
130 };
131 let unit = ui::input::Granularity::of_clicks(click_count);
132 self.selection = match modifiers.shift {
135 true => self.selection.extend_to(hit),
136 false => {
137 let span = hit.span(unit, &self.doc);
138 Selection::new(span.start, span.end)
139 }
140 }
141 .clamp(&self.doc);
142 self.dragging = (!modifiers.shift).then(|| {
143 let (start, end) = self.selection.ordered();
144 (unit, start..end)
145 });
146 self.history.interrupt();
147 self.caret_moved();
148 if let Some(id) = self.anchor_at(position) {
151 cx.emit(EditorEvent::AnchorActivated(id));
152 }
153 cx.notify();
154 }
155
156 pub(super) fn tail_click(
160 &mut self,
161 at: gpui::Point<gpui::Pixels>,
162 cx: &mut Context<Self>,
163 ) -> bool {
164 let Some(last) = self.doc.blocks.len().checked_sub(1) else {
165 return false;
166 };
167 let Some(bounds) = self.layouts.block_bounds(last) else {
168 return false;
169 };
170 at.y > bounds.origin.y + bounds.size.height && self.append_tail(cx)
171 }
172}