This commit is contained in:
Antonio Scandurra
2023-11-30 18:00:41 +01:00
parent 5243401afa
commit 0e1597d385
5 changed files with 155 additions and 55 deletions
+19 -18
View File
@@ -1734,21 +1734,11 @@ impl Editor {
// Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
// }
// pub fn auto_height(
// max_lines: usize,
// field_editor_style: Option<Arc<GetFieldEditorTheme>>,
// cx: &mut ViewContext<Self>,
// ) -> Self {
// let buffer = cx.build_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
// let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
// Self::new(
// EditorMode::AutoHeight { max_lines },
// buffer,
// None,
// field_editor_style,
// cx,
// )
// }
pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::AutoHeight { max_lines }, buffer, None, cx)
}
pub fn for_buffer(
buffer: Model<Buffer>,
@@ -2908,6 +2898,7 @@ impl Editor {
}
pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
dbg!("!!!!!!!!!!");
self.transact(cx, |this, cx| {
let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
let selections = this.selections.all::<usize>(cx);
@@ -8374,6 +8365,18 @@ impl Editor {
cx.notify();
}
pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
let rem_size = cx.rem_size();
self.display_map.update(cx, |map, cx| {
map.set_font(
style.text.font(),
style.text.font_size.to_pixels(rem_size),
cx,
)
});
self.style = Some(style);
}
pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
self.display_map
.update(cx, |map, cx| map.set_wrap_width(width, cx))
@@ -9397,7 +9400,7 @@ impl Render for Editor {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let settings = ThemeSettings::get_global(cx);
let text_style = match self.mode {
EditorMode::SingleLine => TextStyle {
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
color: cx.theme().colors().text,
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features,
@@ -9410,8 +9413,6 @@ impl Render for Editor {
white_space: WhiteSpace::Normal,
},
EditorMode::AutoHeight { max_lines } => todo!(),
EditorMode::Full => TextStyle {
color: cx.theme().colors().text,
font_family: settings.buffer_font.family.clone(),
+98 -37
View File
@@ -20,9 +20,9 @@ use crate::{
use anyhow::Result;
use collections::{BTreeMap, HashMap};
use gpui::{
div, point, px, relative, size, transparent_black, Action, AnyElement, AvailableSpace,
BorrowWindow, Bounds, ContentMask, Corners, DispatchPhase, Edges, Element, ElementId,
ElementInputHandler, Entity, EntityId, Hsla, InteractiveBounds, InteractiveElement,
div, point, px, relative, size, transparent_black, Action, AnyElement, AsyncWindowContext,
AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, DispatchPhase, Edges, Element,
ElementId, ElementInputHandler, Entity, EntityId, Hsla, InteractiveBounds, InteractiveElement,
IntoElement, LineLayout, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
ParentElement, Pixels, RenderOnce, ScrollWheelEvent, ShapedLine, SharedString, Size,
StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, TextStyle, View,
@@ -1662,11 +1662,6 @@ impl EditorElement {
cx: &mut WindowContext,
) -> LayoutState {
self.editor.update(cx, |editor, cx| {
// let mut size = constraint.max;
// if size.x.is_infinite() {
// unimplemented!("we don't yet handle an infinite width constraint on buffer elements");
// }
let snapshot = editor.snapshot(cx);
let style = self.style.clone();
@@ -1702,6 +1697,7 @@ impl EditorElement {
};
editor.gutter_width = gutter_width;
let text_width = bounds.size.width - gutter_width;
let overscroll = size(em_width, px(0.));
let snapshot = {
@@ -1714,6 +1710,8 @@ impl EditorElement {
SoftWrap::Column(column) => editor_width.min(column as f32 * em_advance),
};
dbg!(bounds.size.width, gutter_width, gutter_margin, overscroll.width, em_width, em_advance, wrap_width);
println!("setting wrap width during paint: {wrap_width:?}");
if editor.set_wrap_width(Some(wrap_width), cx) {
editor.snapshot(cx)
} else {
@@ -1728,25 +1726,6 @@ impl EditorElement {
.collect::<SmallVec<[_; 2]>>();
let scroll_height = Pixels::from(snapshot.max_point().row() + 1) * line_height;
// todo!("this should happen during layout")
let editor_mode = snapshot.mode;
if let EditorMode::AutoHeight { max_lines } = editor_mode {
todo!()
// size.set_y(
// scroll_height
// .min(constraint.max_along(Axis::Vertical))
// .max(constraint.min_along(Axis::Vertical))
// .max(line_height)
// .min(line_height * max_lines as f32),
// )
} else if let EditorMode::SingleLine = editor_mode {
bounds.size.height = line_height.min(bounds.size.height);
}
// todo!()
// else if size.y.is_infinite() {
// // size.set_y(scroll_height);
// }
//
let gutter_size = size(gutter_width, bounds.size.height);
let text_size = size(text_width, bounds.size.height);
@@ -2064,7 +2043,7 @@ impl EditorElement {
.unwrap();
LayoutState {
mode: editor_mode,
mode: snapshot.mode,
position_map: Arc::new(PositionMap {
size: bounds.size,
scroll_position: point(
@@ -2617,19 +2596,44 @@ impl Element for EditorElement {
cx: &mut gpui::WindowContext,
) -> (gpui::LayoutId, Self::State) {
self.editor.update(cx, |editor, cx| {
editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this.
editor.set_style(self.style.clone(), cx);
let rem_size = cx.rem_size();
let mut style = Style::default();
style.size.width = relative(1.).into();
style.size.height = match editor.mode {
let layout_id = match editor.mode {
EditorMode::SingleLine => {
self.style.text.line_height_in_pixels(cx.rem_size()).into()
let rem_size = cx.rem_size();
let mut style = Style::default();
style.size.width = relative(1.).into();
style.size.height = self.style.text.line_height_in_pixels(rem_size).into();
cx.request_layout(&style, None)
}
EditorMode::AutoHeight { max_lines } => {
let editor_handle = cx.view().clone();
let max_line_number_width =
self.max_line_number_width(&editor.snapshot(cx), cx);
cx.request_measured_layout(
Style::default(),
move |known_dimensions, available_space, cx| {
editor_handle
.update(cx, |editor, cx| {
dbg!(compute_auto_height_layout(
editor,
max_lines,
max_line_number_width,
known_dimensions,
cx,
))
})
.unwrap_or_default()
},
)
}
EditorMode::Full => {
let mut style = Style::default();
style.size.width = relative(1.).into();
style.size.height = relative(1.).into();
cx.request_layout(&style, None)
}
EditorMode::AutoHeight { .. } => todo!(),
EditorMode::Full => relative(1.).into(),
};
let layout_id = cx.request_layout(&style, None);
(layout_id, ())
})
@@ -4134,3 +4138,60 @@ pub fn register_action<T: Action>(
}
})
}
fn compute_auto_height_layout(
editor: &mut Editor,
max_lines: usize,
max_line_number_width: Pixels,
known_dimensions: Size<Option<Pixels>>,
cx: &mut ViewContext<Editor>,
) -> Option<Size<Pixels>> {
let mut width = known_dimensions.width?;
if let Some(height) = known_dimensions.height {
return Some(size(width, height));
}
let style = editor.style.as_ref().unwrap();
let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
let font_size = style.text.font_size.to_pixels(cx.rem_size());
let line_height = style.text.line_height_in_pixels(cx.rem_size());
let em_width = cx
.text_system()
.typographic_bounds(font_id, font_size, 'm')
.unwrap()
.size
.width;
let mut snapshot = editor.snapshot(cx);
let gutter_padding;
let gutter_width;
let gutter_margin;
if snapshot.show_gutter {
let descent = cx.text_system().descent(font_id, font_size).unwrap();
let gutter_padding_factor = 3.5;
gutter_padding = (em_width * gutter_padding_factor).round();
gutter_width = max_line_number_width + gutter_padding * 2.0;
gutter_margin = -descent;
} else {
gutter_padding = Pixels::ZERO;
gutter_width = Pixels::ZERO;
gutter_margin = Pixels::ZERO;
};
editor.gutter_width = gutter_width;
let text_width = width - gutter_width;
let overscroll = size(em_width, px(0.));
let editor_width = text_width - gutter_margin - overscroll.width - em_width;
println!("setting wrap width during layout: {editor_width:?}");
if editor.set_wrap_width(Some(editor_width), cx) {
snapshot = editor.snapshot(cx);
}
let scroll_height = Pixels::from(snapshot.max_point().row() + 1) * line_height;
let height = scroll_height
.max(line_height)
.min(line_height * max_lines as f32);
Some(size(width, height))
}
+2
View File
@@ -1,3 +1,4 @@
mod auto_height_editor;
mod focus;
mod kitchen_sink;
mod picker;
@@ -5,6 +6,7 @@ mod scroll;
mod text;
mod z_index;
pub use auto_height_editor::*;
pub use focus::*;
pub use kitchen_sink::*;
pub use picker::*;
@@ -0,0 +1,34 @@
use editor::Editor;
use gpui::{
div, white, Div, KeyBinding, ParentElement, Render, Styled, View, ViewContext, VisualContext,
WindowContext,
};
pub struct AutoHeightEditorStory {
editor: View<Editor>,
}
impl AutoHeightEditorStory {
pub fn new(cx: &mut WindowContext) -> View<Self> {
cx.bind_keys([KeyBinding::new("enter", editor::Newline, Some("Editor"))]);
cx.build_view(|cx| Self {
editor: cx.build_view(|cx| {
let mut editor = Editor::auto_height(3, cx);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
editor
}),
})
}
}
impl Render for AutoHeightEditorStory {
type Element = Div;
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
div()
.size_full()
.bg(white())
.text_sm()
.child(div().w_32().bg(gpui::black()).child(self.editor.clone()))
}
}
+2
View File
@@ -12,6 +12,7 @@ use ui::prelude::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)]
#[strum(serialize_all = "snake_case")]
pub enum ComponentStory {
AutoHeightEditor,
Avatar,
Button,
Checkbox,
@@ -33,6 +34,7 @@ pub enum ComponentStory {
impl ComponentStory {
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
match self {
Self::AutoHeightEditor => AutoHeightEditorStory::new(cx).into(),
Self::Avatar => cx.build_view(|_| ui::AvatarStory).into(),
Self::Button => cx.build_view(|_| ui::ButtonStory).into(),
Self::Checkbox => cx.build_view(|_| ui::CheckboxStory).into(),