twrite_gpui/editor/
render.rs1use gpui::prelude::*;
2use gpui::{Context, MouseButton, Render, div};
3
4use crate::canvas::EditorCanvas;
5use crate::prompt_bar::PromptBar;
6
7use super::{Editor, SelectionGranularity};
8
9impl Render for Editor {
10 fn render(
11 &mut self,
12 _window: &mut gpui::Window,
13 cx: &mut Context<Self>,
14 ) -> impl gpui::prelude::IntoElement {
15 let cursor_style = if self.is_hovering_task || self.hovered_link.is_some() {
16 gpui::CursorStyle::PointingHand
17 } else {
18 gpui::CursorStyle::IBeam
19 };
20
21 let root = div()
22 .track_focus(&self.focus_handle)
23 .key_context("Editor")
24 .size_full()
25 .flex()
26 .flex_col()
27 .overflow_hidden()
28 .cursor(cursor_style)
29 .bg(self.theme.background);
30 let root = if let Some(family) = self
31 .config
32 .font_family
33 .clone()
34 .or_else(|| self.selected_font_family.clone())
35 {
36 root.font_family(family)
37 } else {
38 root
39 };
40
41 let root = root
42 .on_key_down(cx.listener(Self::handle_key_down))
43 .on_mouse_down(MouseButton::Left, cx.listener(Self::handle_mouse_down))
44 .on_mouse_down(MouseButton::Right, cx.listener(Self::handle_right_click))
45 .on_mouse_up(MouseButton::Left, cx.listener(Self::handle_mouse_up))
46 .on_mouse_up_out(
47 MouseButton::Left,
48 cx.listener(|this, _, _, cx| {
49 this.is_selecting = false;
50 this.drag_initial_range = None;
51 this.selection_granularity = SelectionGranularity::Character;
52 if let Some(sel) = this.selection
53 && sel.is_empty()
54 {
55 this.selection = None;
56 }
57 for hook in &mut this.hooks {
58 hook.on_selection_change(&this.buffer, this.selection.as_ref());
59 }
60 let changed = this.is_hovering_task || this.hovered_link.is_some();
61 this.is_hovering_task = false;
62 this.hovered_link = None;
63 if changed {
64 cx.notify();
65 }
66 }),
67 )
68 .on_mouse_move(cx.listener(Self::handle_mouse_move))
69 .on_scroll_wheel(cx.listener(Self::handle_scroll_wheel))
70 .child(
71 div()
72 .flex_1()
73 .overflow_hidden()
74 .child(EditorCanvas::new(cx.entity().clone())),
75 );
76
77 let root = root.child(self.render_context_menu(cx));
78 if !self.prompt.is_open() {
79 return root;
80 }
81 let snapshot = self.search_snapshot();
82 let placement = self
83 .prompt
84 .spec()
85 .map(|s| s.placement)
86 .unwrap_or(twrite_core::PromptPlacement::BottomBar);
87 match placement {
88 twrite_core::PromptPlacement::TopPalette => {
89 root.child(PromptBar::palette(&self.prompt, snapshot, cx))
90 }
91 twrite_core::PromptPlacement::BottomBar => {
92 root.child(PromptBar::bottom_bar(&self.prompt, snapshot, cx))
93 }
94 }
95 }
96}