WIP
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user