mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 18:41:56 +03:00
commit
c9be637b6b
@ -162,7 +162,7 @@ impl WrapMap {
|
|||||||
{
|
{
|
||||||
let tab_snapshot = new_snapshot.tab_snapshot.clone();
|
let tab_snapshot = new_snapshot.tab_snapshot.clone();
|
||||||
let range = TabPoint::zero()..tab_snapshot.max_point();
|
let range = TabPoint::zero()..tab_snapshot.max_point();
|
||||||
let edits = new_snapshot
|
edits = new_snapshot
|
||||||
.update(
|
.update(
|
||||||
tab_snapshot,
|
tab_snapshot,
|
||||||
&[TabEdit {
|
&[TabEdit {
|
||||||
|
@ -1734,21 +1734,11 @@ impl Editor {
|
|||||||
// Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
|
// Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// pub fn auto_height(
|
pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
|
||||||
// max_lines: usize,
|
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
|
||||||
// field_editor_style: Option<Arc<GetFieldEditorTheme>>,
|
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||||
// cx: &mut ViewContext<Self>,
|
Self::new(EditorMode::AutoHeight { max_lines }, buffer, None, cx)
|
||||||
// ) -> 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 for_buffer(
|
pub fn for_buffer(
|
||||||
buffer: Model<Buffer>,
|
buffer: Model<Buffer>,
|
||||||
@ -8374,6 +8364,18 @@ impl Editor {
|
|||||||
cx.notify();
|
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 {
|
pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
|
||||||
self.display_map
|
self.display_map
|
||||||
.update(cx, |map, cx| map.set_wrap_width(width, cx))
|
.update(cx, |map, cx| map.set_wrap_width(width, cx))
|
||||||
@ -9397,7 +9399,7 @@ impl Render for Editor {
|
|||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let settings = ThemeSettings::get_global(cx);
|
let settings = ThemeSettings::get_global(cx);
|
||||||
let text_style = match self.mode {
|
let text_style = match self.mode {
|
||||||
EditorMode::SingleLine => TextStyle {
|
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
|
||||||
color: cx.theme().colors().text,
|
color: cx.theme().colors().text,
|
||||||
font_family: settings.ui_font.family.clone(),
|
font_family: settings.ui_font.family.clone(),
|
||||||
font_features: settings.ui_font.features,
|
font_features: settings.ui_font.features,
|
||||||
@ -9410,8 +9412,6 @@ impl Render for Editor {
|
|||||||
white_space: WhiteSpace::Normal,
|
white_space: WhiteSpace::Normal,
|
||||||
},
|
},
|
||||||
|
|
||||||
EditorMode::AutoHeight { max_lines } => todo!(),
|
|
||||||
|
|
||||||
EditorMode::Full => TextStyle {
|
EditorMode::Full => TextStyle {
|
||||||
color: cx.theme().colors().text,
|
color: cx.theme().colors().text,
|
||||||
font_family: settings.buffer_font.family.clone(),
|
font_family: settings.buffer_font.family.clone(),
|
||||||
|
@ -20,9 +20,9 @@ use crate::{
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::{BTreeMap, HashMap};
|
use collections::{BTreeMap, HashMap};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, point, px, relative, size, transparent_black, Action, AnyElement, AvailableSpace,
|
div, point, px, relative, size, transparent_black, Action, AnyElement, AsyncWindowContext,
|
||||||
BorrowWindow, Bounds, ContentMask, Corners, DispatchPhase, Edges, Element, ElementId,
|
AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, DispatchPhase, Edges, Element,
|
||||||
ElementInputHandler, Entity, EntityId, Hsla, InteractiveBounds, InteractiveElement,
|
ElementId, ElementInputHandler, Entity, EntityId, Hsla, InteractiveBounds, InteractiveElement,
|
||||||
IntoElement, LineLayout, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
IntoElement, LineLayout, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||||
ParentElement, Pixels, RenderOnce, ScrollWheelEvent, ShapedLine, SharedString, Size,
|
ParentElement, Pixels, RenderOnce, ScrollWheelEvent, ShapedLine, SharedString, Size,
|
||||||
StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, TextStyle, View,
|
StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, TextStyle, View,
|
||||||
@ -1662,11 +1662,6 @@ impl EditorElement {
|
|||||||
cx: &mut WindowContext,
|
cx: &mut WindowContext,
|
||||||
) -> LayoutState {
|
) -> LayoutState {
|
||||||
self.editor.update(cx, |editor, cx| {
|
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 snapshot = editor.snapshot(cx);
|
||||||
let style = self.style.clone();
|
let style = self.style.clone();
|
||||||
|
|
||||||
@ -1702,6 +1697,7 @@ impl EditorElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
editor.gutter_width = gutter_width;
|
editor.gutter_width = gutter_width;
|
||||||
|
|
||||||
let text_width = bounds.size.width - gutter_width;
|
let text_width = bounds.size.width - gutter_width;
|
||||||
let overscroll = size(em_width, px(0.));
|
let overscroll = size(em_width, px(0.));
|
||||||
let snapshot = {
|
let snapshot = {
|
||||||
@ -1728,25 +1724,6 @@ impl EditorElement {
|
|||||||
.collect::<SmallVec<[_; 2]>>();
|
.collect::<SmallVec<[_; 2]>>();
|
||||||
|
|
||||||
let scroll_height = Pixels::from(snapshot.max_point().row() + 1) * line_height;
|
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 gutter_size = size(gutter_width, bounds.size.height);
|
||||||
let text_size = size(text_width, bounds.size.height);
|
let text_size = size(text_width, bounds.size.height);
|
||||||
|
|
||||||
@ -2064,7 +2041,7 @@ impl EditorElement {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
LayoutState {
|
LayoutState {
|
||||||
mode: editor_mode,
|
mode: snapshot.mode,
|
||||||
position_map: Arc::new(PositionMap {
|
position_map: Arc::new(PositionMap {
|
||||||
size: bounds.size,
|
size: bounds.size,
|
||||||
scroll_position: point(
|
scroll_position: point(
|
||||||
@ -2617,19 +2594,44 @@ impl Element for EditorElement {
|
|||||||
cx: &mut gpui::WindowContext,
|
cx: &mut gpui::WindowContext,
|
||||||
) -> (gpui::LayoutId, Self::State) {
|
) -> (gpui::LayoutId, Self::State) {
|
||||||
self.editor.update(cx, |editor, cx| {
|
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 layout_id = match editor.mode {
|
||||||
let mut style = Style::default();
|
|
||||||
style.size.width = relative(1.).into();
|
|
||||||
style.size.height = match editor.mode {
|
|
||||||
EditorMode::SingleLine => {
|
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| {
|
||||||
|
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, ())
|
(layout_id, ())
|
||||||
})
|
})
|
||||||
@ -2698,604 +2700,6 @@ impl IntoElement for EditorElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl EditorElement {
|
|
||||||
// type LayoutState = LayoutState;
|
|
||||||
// type PaintState = ();
|
|
||||||
|
|
||||||
// fn layout(
|
|
||||||
// &mut self,
|
|
||||||
// constraint: SizeConstraint,
|
|
||||||
// editor: &mut Editor,
|
|
||||||
// cx: &mut ViewContext<Editor>,
|
|
||||||
// ) -> (gpui::Point<Pixels>, Self::LayoutState) {
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
// let line_height = (style.text.font_size * style.line_height_scalar).round();
|
|
||||||
|
|
||||||
// let gutter_padding;
|
|
||||||
// let gutter_width;
|
|
||||||
// let gutter_margin;
|
|
||||||
// if snapshot.show_gutter {
|
|
||||||
// let em_width = style.text.em_width(cx.font_cache());
|
|
||||||
// gutter_padding = (em_width * style.gutter_padding_factor).round();
|
|
||||||
// gutter_width = self.max_line_number_width(&snapshot, cx) + gutter_padding * 2.0;
|
|
||||||
// gutter_margin = -style.text.descent(cx.font_cache());
|
|
||||||
// } else {
|
|
||||||
// gutter_padding = 0.0;
|
|
||||||
// gutter_width = 0.0;
|
|
||||||
// gutter_margin = 0.0;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let text_width = size.x - gutter_width;
|
|
||||||
// let em_width = style.text.em_width(cx.font_cache());
|
|
||||||
// let em_advance = style.text.em_advance(cx.font_cache());
|
|
||||||
// let overscroll = point(em_width, 0.);
|
|
||||||
// let snapshot = {
|
|
||||||
// editor.set_visible_line_count(size.y / line_height, cx);
|
|
||||||
|
|
||||||
// let editor_width = text_width - gutter_margin - overscroll.x - em_width;
|
|
||||||
// let wrap_width = match editor.soft_wrap_mode(cx) {
|
|
||||||
// SoftWrap::None => (MAX_LINE_LEN / 2) as f32 * em_advance,
|
|
||||||
// SoftWrap::EditorWidth => editor_width,
|
|
||||||
// SoftWrap::Column(column) => editor_width.min(column as f32 * em_advance),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if editor.set_wrap_width(Some(wrap_width), cx) {
|
|
||||||
// editor.snapshot(cx)
|
|
||||||
// } else {
|
|
||||||
// snapshot
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let wrap_guides = editor
|
|
||||||
// .wrap_guides(cx)
|
|
||||||
// .iter()
|
|
||||||
// .map(|(guide, active)| (self.column_pixels(*guide, cx), *active))
|
|
||||||
// .collect();
|
|
||||||
|
|
||||||
// let scroll_height = (snapshot.max_point().row() + 1) as f32 * line_height;
|
|
||||||
// if let EditorMode::AutoHeight { max_lines } = snapshot.mode {
|
|
||||||
// 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 = snapshot.mode {
|
|
||||||
// size.set_y(line_height.max(constraint.min_along(Axis::Vertical)))
|
|
||||||
// } else if size.y.is_infinite() {
|
|
||||||
// size.set_y(scroll_height);
|
|
||||||
// }
|
|
||||||
// let gutter_size = point(gutter_width, size.y);
|
|
||||||
// let text_size = point(text_width, size.y);
|
|
||||||
|
|
||||||
// let autoscroll_horizontally = editor.autoscroll_vertically(size.y, line_height, cx);
|
|
||||||
// let mut snapshot = editor.snapshot(cx);
|
|
||||||
|
|
||||||
// let scroll_position = snapshot.scroll_position();
|
|
||||||
// // The scroll position is a fractional point, the whole number of which represents
|
|
||||||
// // the top of the window in terms of display rows.
|
|
||||||
// let start_row = scroll_position.y as u32;
|
|
||||||
// let height_in_lines = size.y / line_height;
|
|
||||||
// let max_row = snapshot.max_point().row();
|
|
||||||
|
|
||||||
// // Add 1 to ensure selections bleed off screen
|
|
||||||
// let end_row = 1 + cmp::min(
|
|
||||||
// (scroll_position.y + height_in_lines).ceil() as u32,
|
|
||||||
// max_row,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let start_anchor = if start_row == 0 {
|
|
||||||
// Anchor::min()
|
|
||||||
// } else {
|
|
||||||
// snapshot
|
|
||||||
// .buffer_snapshot
|
|
||||||
// .anchor_before(DisplayPoint::new(start_row, 0).to_offset(&snapshot, Bias::Left))
|
|
||||||
// };
|
|
||||||
// let end_anchor = if end_row > max_row {
|
|
||||||
// Anchor::max
|
|
||||||
// } else {
|
|
||||||
// snapshot
|
|
||||||
// .buffer_snapshot
|
|
||||||
// .anchor_before(DisplayPoint::new(end_row, 0).to_offset(&snapshot, Bias::Right))
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let mut selections: Vec<(SelectionStyle, Vec<SelectionLayout>)> = Vec::new();
|
|
||||||
// let mut active_rows = BTreeMap::new();
|
|
||||||
// let mut fold_ranges = Vec::new();
|
|
||||||
// let is_singleton = editor.is_singleton(cx);
|
|
||||||
|
|
||||||
// let highlighted_rows = editor.highlighted_rows();
|
|
||||||
// let theme = theme::current(cx);
|
|
||||||
// let highlighted_ranges = editor.background_highlights_in_range(
|
|
||||||
// start_anchor..end_anchor,
|
|
||||||
// &snapshot.display_snapshot,
|
|
||||||
// theme.as_ref(),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// fold_ranges.extend(
|
|
||||||
// snapshot
|
|
||||||
// .folds_in_range(start_anchor..end_anchor)
|
|
||||||
// .map(|anchor| {
|
|
||||||
// let start = anchor.start.to_point(&snapshot.buffer_snapshot);
|
|
||||||
// (
|
|
||||||
// start.row,
|
|
||||||
// start.to_display_point(&snapshot.display_snapshot)
|
|
||||||
// ..anchor.end.to_display_point(&snapshot),
|
|
||||||
// )
|
|
||||||
// }),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let mut newest_selection_head = None;
|
|
||||||
|
|
||||||
// if editor.show_local_selections {
|
|
||||||
// let mut local_selections: Vec<Selection<Point>> = editor
|
|
||||||
// .selections
|
|
||||||
// .disjoint_in_range(start_anchor..end_anchor, cx);
|
|
||||||
// local_selections.extend(editor.selections.pending(cx));
|
|
||||||
// let mut layouts = Vec::new();
|
|
||||||
// let newest = editor.selections.newest(cx);
|
|
||||||
// for selection in local_selections.drain(..) {
|
|
||||||
// let is_empty = selection.start == selection.end;
|
|
||||||
// let is_newest = selection == newest;
|
|
||||||
|
|
||||||
// let layout = SelectionLayout::new(
|
|
||||||
// selection,
|
|
||||||
// editor.selections.line_mode,
|
|
||||||
// editor.cursor_shape,
|
|
||||||
// &snapshot.display_snapshot,
|
|
||||||
// is_newest,
|
|
||||||
// true,
|
|
||||||
// );
|
|
||||||
// if is_newest {
|
|
||||||
// newest_selection_head = Some(layout.head);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for row in cmp::max(layout.active_rows.start, start_row)
|
|
||||||
// ..=cmp::min(layout.active_rows.end, end_row)
|
|
||||||
// {
|
|
||||||
// let contains_non_empty_selection = active_rows.entry(row).or_insert(!is_empty);
|
|
||||||
// *contains_non_empty_selection |= !is_empty;
|
|
||||||
// }
|
|
||||||
// layouts.push(layout);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// selections.push((style.selection, layouts));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if let Some(collaboration_hub) = &editor.collaboration_hub {
|
|
||||||
// // When following someone, render the local selections in their color.
|
|
||||||
// if let Some(leader_id) = editor.leader_peer_id {
|
|
||||||
// if let Some(collaborator) = collaboration_hub.collaborators(cx).get(&leader_id) {
|
|
||||||
// if let Some(participant_index) = collaboration_hub
|
|
||||||
// .user_participant_indices(cx)
|
|
||||||
// .get(&collaborator.user_id)
|
|
||||||
// {
|
|
||||||
// if let Some((local_selection_style, _)) = selections.first_mut() {
|
|
||||||
// *local_selection_style =
|
|
||||||
// style.selection_style_for_room_participant(participant_index.0);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut remote_selections = HashMap::default();
|
|
||||||
// for selection in snapshot.remote_selections_in_range(
|
|
||||||
// &(start_anchor..end_anchor),
|
|
||||||
// collaboration_hub.as_ref(),
|
|
||||||
// cx,
|
|
||||||
// ) {
|
|
||||||
// let selection_style = if let Some(participant_index) = selection.participant_index {
|
|
||||||
// style.selection_style_for_room_participant(participant_index.0)
|
|
||||||
// } else {
|
|
||||||
// style.absent_selection
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // Don't re-render the leader's selections, since the local selections
|
|
||||||
// // match theirs.
|
|
||||||
// if Some(selection.peer_id) == editor.leader_peer_id {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// remote_selections
|
|
||||||
// .entry(selection.replica_id)
|
|
||||||
// .or_insert((selection_style, Vec::new()))
|
|
||||||
// .1
|
|
||||||
// .push(SelectionLayout::new(
|
|
||||||
// selection.selection,
|
|
||||||
// selection.line_mode,
|
|
||||||
// selection.cursor_shape,
|
|
||||||
// &snapshot.display_snapshot,
|
|
||||||
// false,
|
|
||||||
// false,
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// selections.extend(remote_selections.into_values());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let scrollbar_settings = &settings::get::<EditorSettings>(cx).scrollbar;
|
|
||||||
// let show_scrollbars = match scrollbar_settings.show {
|
|
||||||
// ShowScrollbar::Auto => {
|
|
||||||
// // Git
|
|
||||||
// (is_singleton && scrollbar_settings.git_diff && snapshot.buffer_snapshot.has_git_diffs())
|
|
||||||
// ||
|
|
||||||
// // Selections
|
|
||||||
// (is_singleton && scrollbar_settings.selections && !highlighted_ranges.is_empty)
|
|
||||||
// // Scrollmanager
|
|
||||||
// || editor.scroll_manager.scrollbars_visible()
|
|
||||||
// }
|
|
||||||
// ShowScrollbar::System => editor.scroll_manager.scrollbars_visible(),
|
|
||||||
// ShowScrollbar::Always => true,
|
|
||||||
// ShowScrollbar::Never => false,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let fold_ranges: Vec<(BufferRow, Range<DisplayPoint>, Color)> = fold_ranges
|
|
||||||
// .into_iter()
|
|
||||||
// .map(|(id, fold)| {
|
|
||||||
// let color = self
|
|
||||||
// .style
|
|
||||||
// .folds
|
|
||||||
// .ellipses
|
|
||||||
// .background
|
|
||||||
// .style_for(&mut cx.mouse_state::<FoldMarkers>(id as usize))
|
|
||||||
// .color;
|
|
||||||
|
|
||||||
// (id, fold, color)
|
|
||||||
// })
|
|
||||||
// .collect();
|
|
||||||
|
|
||||||
// let head_for_relative = newest_selection_head.unwrap_or_else(|| {
|
|
||||||
// let newest = editor.selections.newest::<Point>(cx);
|
|
||||||
// SelectionLayout::new(
|
|
||||||
// newest,
|
|
||||||
// editor.selections.line_mode,
|
|
||||||
// editor.cursor_shape,
|
|
||||||
// &snapshot.display_snapshot,
|
|
||||||
// true,
|
|
||||||
// true,
|
|
||||||
// )
|
|
||||||
// .head
|
|
||||||
// });
|
|
||||||
|
|
||||||
// let (line_number_layouts, fold_statuses) = self.layout_line_numbers(
|
|
||||||
// start_row..end_row,
|
|
||||||
// &active_rows,
|
|
||||||
// head_for_relative,
|
|
||||||
// is_singleton,
|
|
||||||
// &snapshot,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let display_hunks = self.layout_git_gutters(start_row..end_row, &snapshot);
|
|
||||||
|
|
||||||
// let scrollbar_row_range = scroll_position.y..(scroll_position.y + height_in_lines);
|
|
||||||
|
|
||||||
// let mut max_visible_line_width = 0.0;
|
|
||||||
// let line_layouts =
|
|
||||||
// self.layout_lines(start_row..end_row, &line_number_layouts, &snapshot, cx);
|
|
||||||
// for line_with_invisibles in &line_layouts {
|
|
||||||
// if line_with_invisibles.line.width() > max_visible_line_width {
|
|
||||||
// max_visible_line_width = line_with_invisibles.line.width();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let style = self.style.clone();
|
|
||||||
// let longest_line_width = layout_line(
|
|
||||||
// snapshot.longest_row(),
|
|
||||||
// &snapshot,
|
|
||||||
// &style,
|
|
||||||
// cx.text_layout_cache(),
|
|
||||||
// )
|
|
||||||
// .width();
|
|
||||||
// let scroll_width = longest_line_width.max(max_visible_line_width) + overscroll.x;
|
|
||||||
// let em_width = style.text.em_width(cx.font_cache());
|
|
||||||
// let (scroll_width, blocks) = self.layout_blocks(
|
|
||||||
// start_row..end_row,
|
|
||||||
// &snapshot,
|
|
||||||
// size.x,
|
|
||||||
// scroll_width,
|
|
||||||
// gutter_padding,
|
|
||||||
// gutter_width,
|
|
||||||
// em_width,
|
|
||||||
// gutter_width + gutter_margin,
|
|
||||||
// line_height,
|
|
||||||
// &style,
|
|
||||||
// &line_layouts,
|
|
||||||
// editor,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let scroll_max = point(
|
|
||||||
// ((scroll_width - text_size.x) / em_width).max(0.0),
|
|
||||||
// max_row as f32,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let clamped = editor.scroll_manager.clamp_scroll_left(scroll_max.x);
|
|
||||||
|
|
||||||
// let autoscrolled = if autoscroll_horizontally {
|
|
||||||
// editor.autoscroll_horizontally(
|
|
||||||
// start_row,
|
|
||||||
// text_size.x,
|
|
||||||
// scroll_width,
|
|
||||||
// em_width,
|
|
||||||
// &line_layouts,
|
|
||||||
// cx,
|
|
||||||
// )
|
|
||||||
// } else {
|
|
||||||
// false
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if clamped || autoscrolled {
|
|
||||||
// snapshot = editor.snapshot(cx);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let style = editor.style(cx);
|
|
||||||
|
|
||||||
// let mut context_menu = None;
|
|
||||||
// let mut code_actions_indicator = None;
|
|
||||||
// if let Some(newest_selection_head) = newest_selection_head {
|
|
||||||
// if (start_row..end_row).contains(&newest_selection_head.row()) {
|
|
||||||
// if editor.context_menu_visible() {
|
|
||||||
// context_menu =
|
|
||||||
// editor.render_context_menu(newest_selection_head, style.clone(), cx);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let active = matches!(
|
|
||||||
// editor.context_menu.read().as_ref(),
|
|
||||||
// Some(crate::ContextMenu::CodeActions(_))
|
|
||||||
// );
|
|
||||||
|
|
||||||
// code_actions_indicator = editor
|
|
||||||
// .render_code_actions_indicator(&style, active, cx)
|
|
||||||
// .map(|indicator| (newest_selection_head.row(), indicator));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let visible_rows = start_row..start_row + line_layouts.len() as u32;
|
|
||||||
// let mut hover = editor.hover_state.render(
|
|
||||||
// &snapshot,
|
|
||||||
// &style,
|
|
||||||
// visible_rows,
|
|
||||||
// editor.workspace.as_ref().map(|(w, _)| w.clone()),
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
// let mode = editor.mode;
|
|
||||||
|
|
||||||
// let mut fold_indicators = editor.render_fold_indicators(
|
|
||||||
// fold_statuses,
|
|
||||||
// &style,
|
|
||||||
// editor.gutter_hovered,
|
|
||||||
// line_height,
|
|
||||||
// gutter_margin,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if let Some((_, context_menu)) = context_menu.as_mut() {
|
|
||||||
// context_menu.layout(
|
|
||||||
// SizeConstraint {
|
|
||||||
// min: gpui::Point::<Pixels>::zero(),
|
|
||||||
// max: point(
|
|
||||||
// cx.window_size().x * 0.7,
|
|
||||||
// (12. * line_height).min((size.y - line_height) / 2.),
|
|
||||||
// ),
|
|
||||||
// },
|
|
||||||
// editor,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if let Some((_, indicator)) = code_actions_indicator.as_mut() {
|
|
||||||
// indicator.layout(
|
|
||||||
// SizeConstraint::strict_along(
|
|
||||||
// Axis::Vertical,
|
|
||||||
// line_height * style.code_actions.vertical_scale,
|
|
||||||
// ),
|
|
||||||
// editor,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for fold_indicator in fold_indicators.iter_mut() {
|
|
||||||
// if let Some(indicator) = fold_indicator.as_mut() {
|
|
||||||
// indicator.layout(
|
|
||||||
// SizeConstraint::strict_along(
|
|
||||||
// Axis::Vertical,
|
|
||||||
// line_height * style.code_actions.vertical_scale,
|
|
||||||
// ),
|
|
||||||
// editor,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if let Some((_, hover_popovers)) = hover.as_mut() {
|
|
||||||
// for hover_popover in hover_popovers.iter_mut() {
|
|
||||||
// hover_popover.layout(
|
|
||||||
// SizeConstraint {
|
|
||||||
// min: gpui::Point::<Pixels>::zero(),
|
|
||||||
// max: point(
|
|
||||||
// (120. * em_width) // Default size
|
|
||||||
// .min(size.x / 2.) // Shrink to half of the editor width
|
|
||||||
// .max(MIN_POPOVER_CHARACTER_WIDTH * em_width), // Apply minimum width of 20 characters
|
|
||||||
// (16. * line_height) // Default size
|
|
||||||
// .min(size.y / 2.) // Shrink to half of the editor height
|
|
||||||
// .max(MIN_POPOVER_LINE_HEIGHT * line_height), // Apply minimum height of 4 lines
|
|
||||||
// ),
|
|
||||||
// },
|
|
||||||
// editor,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let invisible_symbol_font_size = self.style.text.font_size / 2.0;
|
|
||||||
// let invisible_symbol_style = RunStyle {
|
|
||||||
// color: self.style.whitespace,
|
|
||||||
// font_id: self.style.text.font_id,
|
|
||||||
// underline: Default::default(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// (
|
|
||||||
// size,
|
|
||||||
// LayoutState {
|
|
||||||
// mode,
|
|
||||||
// position_map: Arc::new(PositionMap {
|
|
||||||
// size,
|
|
||||||
// scroll_max,
|
|
||||||
// line_layouts,
|
|
||||||
// line_height,
|
|
||||||
// em_width,
|
|
||||||
// em_advance,
|
|
||||||
// snapshot,
|
|
||||||
// }),
|
|
||||||
// visible_display_row_range: start_row..end_row,
|
|
||||||
// wrap_guides,
|
|
||||||
// gutter_size,
|
|
||||||
// gutter_padding,
|
|
||||||
// text_size,
|
|
||||||
// scrollbar_row_range,
|
|
||||||
// show_scrollbars,
|
|
||||||
// is_singleton,
|
|
||||||
// max_row,
|
|
||||||
// gutter_margin,
|
|
||||||
// active_rows,
|
|
||||||
// highlighted_rows,
|
|
||||||
// highlighted_ranges,
|
|
||||||
// fold_ranges,
|
|
||||||
// line_number_layouts,
|
|
||||||
// display_hunks,
|
|
||||||
// blocks,
|
|
||||||
// selections,
|
|
||||||
// context_menu,
|
|
||||||
// code_actions_indicator,
|
|
||||||
// fold_indicators,
|
|
||||||
// tab_invisible: cx.text_layout_cache().layout_str(
|
|
||||||
// "→",
|
|
||||||
// invisible_symbol_font_size,
|
|
||||||
// &[("→".len(), invisible_symbol_style)],
|
|
||||||
// ),
|
|
||||||
// space_invisible: cx.text_layout_cache().layout_str(
|
|
||||||
// "•",
|
|
||||||
// invisible_symbol_font_size,
|
|
||||||
// &[("•".len(), invisible_symbol_style)],
|
|
||||||
// ),
|
|
||||||
// hover_popovers: hover,
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn paint(
|
|
||||||
// &mut self,
|
|
||||||
// bounds: Bounds<Pixels>,
|
|
||||||
// visible_bounds: Bounds<Pixels>,
|
|
||||||
// layout: &mut Self::LayoutState,
|
|
||||||
// editor: &mut Editor,
|
|
||||||
// cx: &mut ViewContext<Editor>,
|
|
||||||
// ) -> Self::PaintState {
|
|
||||||
// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
|
|
||||||
// cx.scene().push_layer(Some(visible_bounds));
|
|
||||||
|
|
||||||
// let gutter_bounds = Bounds::<Pixels>::new(bounds.origin, layout.gutter_size);
|
|
||||||
// let text_bounds = Bounds::<Pixels>::new(
|
|
||||||
// bounds.origin + point(layout.gutter_size.x, 0.0),
|
|
||||||
// layout.text_size,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// Self::attach_mouse_handlers(
|
|
||||||
// &layout.position_map,
|
|
||||||
// layout.hover_popovers.is_some(),
|
|
||||||
// visible_bounds,
|
|
||||||
// text_bounds,
|
|
||||||
// gutter_bounds,
|
|
||||||
// bounds,
|
|
||||||
// cx,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// self.paint_background(gutter_bounds, text_bounds, layout, cx);
|
|
||||||
// if layout.gutter_size.x > 0. {
|
|
||||||
// self.paint_gutter(gutter_bounds, visible_bounds, layout, editor, cx);
|
|
||||||
// }
|
|
||||||
// self.paint_text(text_bounds, visible_bounds, layout, editor, cx);
|
|
||||||
|
|
||||||
// cx.scene().push_layer(Some(bounds));
|
|
||||||
// if !layout.blocks.is_empty {
|
|
||||||
// self.paint_blocks(bounds, visible_bounds, layout, editor, cx);
|
|
||||||
// }
|
|
||||||
// self.paint_scrollbar(bounds, layout, &editor, cx);
|
|
||||||
// cx.scene().pop_layer();
|
|
||||||
// cx.scene().pop_layer();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn rect_for_text_range(
|
|
||||||
// &self,
|
|
||||||
// range_utf16: Range<usize>,
|
|
||||||
// bounds: Bounds<Pixels>,
|
|
||||||
// _: Bounds<Pixels>,
|
|
||||||
// layout: &Self::LayoutState,
|
|
||||||
// _: &Self::PaintState,
|
|
||||||
// _: &Editor,
|
|
||||||
// _: &ViewContext<Editor>,
|
|
||||||
// ) -> Option<Bounds<Pixels>> {
|
|
||||||
// let text_bounds = Bounds::<Pixels>::new(
|
|
||||||
// bounds.origin + point(layout.gutter_size.x, 0.0),
|
|
||||||
// layout.text_size,
|
|
||||||
// );
|
|
||||||
// let content_origin = text_bounds.origin + point(layout.gutter_margin, 0.);
|
|
||||||
// let scroll_position = layout.position_map.snapshot.scroll_position();
|
|
||||||
// let start_row = scroll_position.y as u32;
|
|
||||||
// let scroll_top = scroll_position.y * layout.position_map.line_height;
|
|
||||||
// let scroll_left = scroll_position.x * layout.position_map.em_width;
|
|
||||||
|
|
||||||
// let range_start = OffsetUtf16(range_utf16.start)
|
|
||||||
// .to_display_point(&layout.position_map.snapshot.display_snapshot);
|
|
||||||
// if range_start.row() < start_row {
|
|
||||||
// return None;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let line = &layout
|
|
||||||
// .position_map
|
|
||||||
// .line_layouts
|
|
||||||
// .get((range_start.row() - start_row) as usize)?
|
|
||||||
// .line;
|
|
||||||
// let range_start_x = line.x_for_index(range_start.column() as usize);
|
|
||||||
// let range_start_y = range_start.row() as f32 * layout.position_map.line_height;
|
|
||||||
// Some(Bounds::<Pixels>::new(
|
|
||||||
// content_origin
|
|
||||||
// + point(
|
|
||||||
// range_start_x,
|
|
||||||
// range_start_y + layout.position_map.line_height,
|
|
||||||
// )
|
|
||||||
// - point(scroll_left, scroll_top),
|
|
||||||
// point(
|
|
||||||
// layout.position_map.em_width,
|
|
||||||
// layout.position_map.line_height,
|
|
||||||
// ),
|
|
||||||
// ))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn debug(
|
|
||||||
// &self,
|
|
||||||
// bounds: Bounds<Pixels>,
|
|
||||||
// _: &Self::LayoutState,
|
|
||||||
// _: &Self::PaintState,
|
|
||||||
// _: &Editor,
|
|
||||||
// _: &ViewContext<Editor>,
|
|
||||||
// ) -> json::Value {
|
|
||||||
// json!({
|
|
||||||
// "type": "BufferElement",
|
|
||||||
// "bounds": bounds.to_json()
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
type BufferRow = u32;
|
type BufferRow = u32;
|
||||||
|
|
||||||
pub struct LayoutState {
|
pub struct LayoutState {
|
||||||
@ -4134,3 +3538,59 @@ 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;
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
@ -315,14 +315,11 @@ impl SelectionsCollection {
|
|||||||
|
|
||||||
let line = display_map.layout_row(row, &text_layout_details);
|
let line = display_map.layout_row(row, &text_layout_details);
|
||||||
|
|
||||||
dbg!("****START COL****");
|
|
||||||
let start_col = line.closest_index_for_x(positions.start) as u32;
|
let start_col = line.closest_index_for_x(positions.start) as u32;
|
||||||
if start_col < line_len || (is_empty && positions.start == line.width) {
|
if start_col < line_len || (is_empty && positions.start == line.width) {
|
||||||
let start = DisplayPoint::new(row, start_col);
|
let start = DisplayPoint::new(row, start_col);
|
||||||
dbg!("****END COL****");
|
|
||||||
let end_col = line.closest_index_for_x(positions.end) as u32;
|
let end_col = line.closest_index_for_x(positions.end) as u32;
|
||||||
let end = DisplayPoint::new(row, end_col);
|
let end = DisplayPoint::new(row, end_col);
|
||||||
dbg!(start_col, end_col);
|
|
||||||
|
|
||||||
Some(Selection {
|
Some(Selection {
|
||||||
id: post_inc(&mut self.next_selection_id),
|
id: post_inc(&mut self.next_selection_id),
|
||||||
|
@ -1256,7 +1256,7 @@ mod tests {
|
|||||||
//
|
//
|
||||||
// TODO: without closing, the opened items do not propagate their history changes for some reason
|
// TODO: without closing, the opened items do not propagate their history changes for some reason
|
||||||
// it does work in real app though, only tests do not propagate.
|
// it does work in real app though, only tests do not propagate.
|
||||||
workspace.update(cx, |_, cx| dbg!(cx.focused()));
|
workspace.update(cx, |_, cx| cx.focused());
|
||||||
|
|
||||||
let initial_history = open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
|
let initial_history = open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -144,7 +144,6 @@ impl TextState {
|
|||||||
runs: Option<Vec<TextRun>>,
|
runs: Option<Vec<TextRun>>,
|
||||||
cx: &mut WindowContext,
|
cx: &mut WindowContext,
|
||||||
) -> LayoutId {
|
) -> LayoutId {
|
||||||
let text_system = cx.text_system().clone();
|
|
||||||
let text_style = cx.text_style();
|
let text_style = cx.text_style();
|
||||||
let font_size = text_style.font_size.to_pixels(cx.rem_size());
|
let font_size = text_style.font_size.to_pixels(cx.rem_size());
|
||||||
let line_height = text_style
|
let line_height = text_style
|
||||||
@ -152,18 +151,16 @@ impl TextState {
|
|||||||
.to_pixels(font_size.into(), cx.rem_size());
|
.to_pixels(font_size.into(), cx.rem_size());
|
||||||
let text = SharedString::from(text);
|
let text = SharedString::from(text);
|
||||||
|
|
||||||
let rem_size = cx.rem_size();
|
|
||||||
|
|
||||||
let runs = if let Some(runs) = runs {
|
let runs = if let Some(runs) = runs {
|
||||||
runs
|
runs
|
||||||
} else {
|
} else {
|
||||||
vec![text_style.to_run(text.len())]
|
vec![text_style.to_run(text.len())]
|
||||||
};
|
};
|
||||||
|
|
||||||
let layout_id = cx.request_measured_layout(Default::default(), rem_size, {
|
let layout_id = cx.request_measured_layout(Default::default(), {
|
||||||
let element_state = self.clone();
|
let element_state = self.clone();
|
||||||
|
|
||||||
move |known_dimensions, available_space| {
|
move |known_dimensions, available_space, cx| {
|
||||||
let wrap_width = if text_style.white_space == WhiteSpace::Normal {
|
let wrap_width = if text_style.white_space == WhiteSpace::Normal {
|
||||||
known_dimensions.width.or(match available_space.width {
|
known_dimensions.width.or(match available_space.width {
|
||||||
crate::AvailableSpace::Definite(x) => Some(x),
|
crate::AvailableSpace::Definite(x) => Some(x),
|
||||||
@ -181,7 +178,8 @@ impl TextState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(lines) = text_system
|
let Some(lines) = cx
|
||||||
|
.text_system()
|
||||||
.shape_text(
|
.shape_text(
|
||||||
&text, font_size, &runs, wrap_width, // Wrap if we know the width.
|
&text, font_size, &runs, wrap_width, // Wrap if we know the width.
|
||||||
)
|
)
|
||||||
|
@ -109,7 +109,6 @@ impl Element for UniformList {
|
|||||||
cx: &mut WindowContext,
|
cx: &mut WindowContext,
|
||||||
) -> (LayoutId, Self::State) {
|
) -> (LayoutId, Self::State) {
|
||||||
let max_items = self.item_count;
|
let max_items = self.item_count;
|
||||||
let rem_size = cx.rem_size();
|
|
||||||
let item_size = state
|
let item_size = state
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.item_size)
|
.map(|s| s.item_size)
|
||||||
@ -120,9 +119,7 @@ impl Element for UniformList {
|
|||||||
.layout(state.map(|s| s.interactive), cx, |style, cx| {
|
.layout(state.map(|s| s.interactive), cx, |style, cx| {
|
||||||
cx.request_measured_layout(
|
cx.request_measured_layout(
|
||||||
style,
|
style,
|
||||||
rem_size,
|
move |known_dimensions, available_space, _cx| {
|
||||||
move |known_dimensions: Size<Option<Pixels>>,
|
|
||||||
available_space: Size<AvailableSpace>| {
|
|
||||||
let desired_height = item_size.height * max_items;
|
let desired_height = item_size.height * max_items;
|
||||||
let width =
|
let width =
|
||||||
known_dimensions
|
known_dimensions
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use super::{AbsoluteLength, Bounds, DefiniteLength, Edges, Length, Pixels, Point, Size, Style};
|
use crate::{
|
||||||
|
AbsoluteLength, Bounds, DefiniteLength, Edges, Length, Pixels, Point, Size, Style,
|
||||||
|
WindowContext,
|
||||||
|
};
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@ -9,13 +12,21 @@ use taffy::{
|
|||||||
Taffy,
|
Taffy,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Measureable = dyn Fn(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels> + Send + Sync;
|
|
||||||
|
|
||||||
pub struct TaffyLayoutEngine {
|
pub struct TaffyLayoutEngine {
|
||||||
taffy: Taffy<Box<Measureable>>,
|
taffy: Taffy,
|
||||||
children_to_parents: HashMap<LayoutId, LayoutId>,
|
children_to_parents: HashMap<LayoutId, LayoutId>,
|
||||||
absolute_layout_bounds: HashMap<LayoutId, Bounds<Pixels>>,
|
absolute_layout_bounds: HashMap<LayoutId, Bounds<Pixels>>,
|
||||||
computed_layouts: HashSet<LayoutId>,
|
computed_layouts: HashSet<LayoutId>,
|
||||||
|
nodes_to_measure: HashMap<
|
||||||
|
LayoutId,
|
||||||
|
Box<
|
||||||
|
dyn FnMut(
|
||||||
|
Size<Option<Pixels>>,
|
||||||
|
Size<AvailableSpace>,
|
||||||
|
&mut WindowContext,
|
||||||
|
) -> Size<Pixels>,
|
||||||
|
>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static EXPECT_MESSAGE: &'static str =
|
static EXPECT_MESSAGE: &'static str =
|
||||||
@ -28,6 +39,7 @@ impl TaffyLayoutEngine {
|
|||||||
children_to_parents: HashMap::default(),
|
children_to_parents: HashMap::default(),
|
||||||
absolute_layout_bounds: HashMap::default(),
|
absolute_layout_bounds: HashMap::default(),
|
||||||
computed_layouts: HashSet::default(),
|
computed_layouts: HashSet::default(),
|
||||||
|
nodes_to_measure: HashMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +48,7 @@ impl TaffyLayoutEngine {
|
|||||||
self.children_to_parents.clear();
|
self.children_to_parents.clear();
|
||||||
self.absolute_layout_bounds.clear();
|
self.absolute_layout_bounds.clear();
|
||||||
self.computed_layouts.clear();
|
self.computed_layouts.clear();
|
||||||
|
self.nodes_to_measure.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_layout(
|
pub fn request_layout(
|
||||||
@ -65,18 +78,18 @@ impl TaffyLayoutEngine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
style: Style,
|
style: Style,
|
||||||
rem_size: Pixels,
|
rem_size: Pixels,
|
||||||
measure: impl Fn(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels>
|
measure: impl FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
+ 'static,
|
||||||
) -> LayoutId {
|
) -> LayoutId {
|
||||||
let style = style.to_taffy(rem_size);
|
let style = style.to_taffy(rem_size);
|
||||||
|
|
||||||
let measurable = Box::new(measure);
|
let layout_id = self
|
||||||
self.taffy
|
.taffy
|
||||||
.new_leaf_with_context(style, measurable)
|
.new_leaf_with_context(style, ())
|
||||||
.expect(EXPECT_MESSAGE)
|
.expect(EXPECT_MESSAGE)
|
||||||
.into()
|
.into();
|
||||||
|
self.nodes_to_measure.insert(layout_id, Box::new(measure));
|
||||||
|
layout_id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to understand performance
|
// Used to understand performance
|
||||||
@ -126,7 +139,12 @@ impl TaffyLayoutEngine {
|
|||||||
Ok(edges)
|
Ok(edges)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_layout(&mut self, id: LayoutId, available_space: Size<AvailableSpace>) {
|
pub fn compute_layout(
|
||||||
|
&mut self,
|
||||||
|
id: LayoutId,
|
||||||
|
available_space: Size<AvailableSpace>,
|
||||||
|
cx: &mut WindowContext,
|
||||||
|
) {
|
||||||
// Leaving this here until we have a better instrumentation approach.
|
// Leaving this here until we have a better instrumentation approach.
|
||||||
// println!("Laying out {} children", self.count_all_children(id)?);
|
// println!("Laying out {} children", self.count_all_children(id)?);
|
||||||
// println!("Max layout depth: {}", self.max_depth(0, id)?);
|
// println!("Max layout depth: {}", self.max_depth(0, id)?);
|
||||||
@ -159,8 +177,8 @@ impl TaffyLayoutEngine {
|
|||||||
.compute_layout_with_measure(
|
.compute_layout_with_measure(
|
||||||
id.into(),
|
id.into(),
|
||||||
available_space.into(),
|
available_space.into(),
|
||||||
|known_dimensions, available_space, _node_id, context| {
|
|known_dimensions, available_space, node_id, _context| {
|
||||||
let Some(measure) = context else {
|
let Some(measure) = self.nodes_to_measure.get_mut(&node_id.into()) else {
|
||||||
return taffy::geometry::Size::default();
|
return taffy::geometry::Size::default();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -169,10 +187,11 @@ impl TaffyLayoutEngine {
|
|||||||
height: known_dimensions.height.map(Pixels),
|
height: known_dimensions.height.map(Pixels),
|
||||||
};
|
};
|
||||||
|
|
||||||
measure(known_dimensions, available_space.into()).into()
|
measure(known_dimensions, available_space.into(), cx).into()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect(EXPECT_MESSAGE);
|
.expect(EXPECT_MESSAGE);
|
||||||
|
|
||||||
// println!("compute_layout took {:?}", started_at.elapsed());
|
// println!("compute_layout took {:?}", started_at.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +209,7 @@ impl AnyView {
|
|||||||
) {
|
) {
|
||||||
cx.with_absolute_element_offset(origin, |cx| {
|
cx.with_absolute_element_offset(origin, |cx| {
|
||||||
let (layout_id, rendered_element) = (self.layout)(self, cx);
|
let (layout_id, rendered_element) = (self.layout)(self, cx);
|
||||||
cx.window
|
cx.compute_layout(layout_id, available_space);
|
||||||
.layout_engine
|
|
||||||
.compute_layout(layout_id, available_space);
|
|
||||||
(self.paint)(self, rendered_element, cx);
|
(self.paint)(self, rendered_element, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ pub struct Window {
|
|||||||
sprite_atlas: Arc<dyn PlatformAtlas>,
|
sprite_atlas: Arc<dyn PlatformAtlas>,
|
||||||
rem_size: Pixels,
|
rem_size: Pixels,
|
||||||
viewport_size: Size<Pixels>,
|
viewport_size: Size<Pixels>,
|
||||||
pub(crate) layout_engine: TaffyLayoutEngine,
|
layout_engine: Option<TaffyLayoutEngine>,
|
||||||
pub(crate) root_view: Option<AnyView>,
|
pub(crate) root_view: Option<AnyView>,
|
||||||
pub(crate) element_id_stack: GlobalElementId,
|
pub(crate) element_id_stack: GlobalElementId,
|
||||||
pub(crate) previous_frame: Frame,
|
pub(crate) previous_frame: Frame,
|
||||||
@ -327,7 +327,7 @@ impl Window {
|
|||||||
sprite_atlas,
|
sprite_atlas,
|
||||||
rem_size: px(16.),
|
rem_size: px(16.),
|
||||||
viewport_size: content_size,
|
viewport_size: content_size,
|
||||||
layout_engine: TaffyLayoutEngine::new(),
|
layout_engine: Some(TaffyLayoutEngine::new()),
|
||||||
root_view: None,
|
root_view: None,
|
||||||
element_id_stack: GlobalElementId::default(),
|
element_id_stack: GlobalElementId::default(),
|
||||||
previous_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
|
previous_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
|
||||||
@ -606,9 +606,11 @@ impl<'a> WindowContext<'a> {
|
|||||||
self.app.layout_id_buffer.extend(children.into_iter());
|
self.app.layout_id_buffer.extend(children.into_iter());
|
||||||
let rem_size = self.rem_size();
|
let rem_size = self.rem_size();
|
||||||
|
|
||||||
self.window
|
self.window.layout_engine.as_mut().unwrap().request_layout(
|
||||||
.layout_engine
|
style,
|
||||||
.request_layout(style, rem_size, &self.app.layout_id_buffer)
|
rem_size,
|
||||||
|
&self.app.layout_id_buffer,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
|
/// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
|
||||||
@ -618,22 +620,25 @@ impl<'a> WindowContext<'a> {
|
|||||||
/// The given closure is invoked at layout time with the known dimensions and available space and
|
/// The given closure is invoked at layout time with the known dimensions and available space and
|
||||||
/// returns a `Size`.
|
/// returns a `Size`.
|
||||||
pub fn request_measured_layout<
|
pub fn request_measured_layout<
|
||||||
F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels> + Send + Sync + 'static,
|
F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
|
||||||
|
+ 'static,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
style: Style,
|
style: Style,
|
||||||
rem_size: Pixels,
|
|
||||||
measure: F,
|
measure: F,
|
||||||
) -> LayoutId {
|
) -> LayoutId {
|
||||||
|
let rem_size = self.rem_size();
|
||||||
self.window
|
self.window
|
||||||
.layout_engine
|
.layout_engine
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
.request_measured_layout(style, rem_size, measure)
|
.request_measured_layout(style, rem_size, measure)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
|
pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
|
||||||
self.window
|
let mut layout_engine = self.window.layout_engine.take().unwrap();
|
||||||
.layout_engine
|
layout_engine.compute_layout(layout_id, available_space, self);
|
||||||
.compute_layout(layout_id, available_space)
|
self.window.layout_engine = Some(layout_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the bounds computed for the given LayoutId relative to the window. This method should not
|
/// Obtain the bounds computed for the given LayoutId relative to the window. This method should not
|
||||||
@ -643,6 +648,8 @@ impl<'a> WindowContext<'a> {
|
|||||||
let mut bounds = self
|
let mut bounds = self
|
||||||
.window
|
.window
|
||||||
.layout_engine
|
.layout_engine
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
.layout_bounds(layout_id)
|
.layout_bounds(layout_id)
|
||||||
.map(Into::into);
|
.map(Into::into);
|
||||||
bounds.origin += self.element_offset();
|
bounds.origin += self.element_offset();
|
||||||
@ -1193,7 +1200,7 @@ impl<'a> WindowContext<'a> {
|
|||||||
self.text_system().start_frame();
|
self.text_system().start_frame();
|
||||||
|
|
||||||
let window = &mut *self.window;
|
let window = &mut *self.window;
|
||||||
window.layout_engine.clear();
|
window.layout_engine.as_mut().unwrap().clear();
|
||||||
|
|
||||||
mem::swap(&mut window.previous_frame, &mut window.current_frame);
|
mem::swap(&mut window.previous_frame, &mut window.current_frame);
|
||||||
let frame = &mut window.current_frame;
|
let frame = &mut window.current_frame;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
mod auto_height_editor;
|
||||||
mod focus;
|
mod focus;
|
||||||
mod kitchen_sink;
|
mod kitchen_sink;
|
||||||
mod picker;
|
mod picker;
|
||||||
@ -5,6 +6,7 @@ mod scroll;
|
|||||||
mod text;
|
mod text;
|
||||||
mod z_index;
|
mod z_index;
|
||||||
|
|
||||||
|
pub use auto_height_editor::*;
|
||||||
pub use focus::*;
|
pub use focus::*;
|
||||||
pub use kitchen_sink::*;
|
pub use kitchen_sink::*;
|
||||||
pub use picker::*;
|
pub use picker::*;
|
||||||
|
34
crates/storybook2/src/stories/auto_height_editor.rs
Normal file
34
crates/storybook2/src/stories/auto_height_editor.rs
Normal file
@ -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)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)]
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
pub enum ComponentStory {
|
pub enum ComponentStory {
|
||||||
|
AutoHeightEditor,
|
||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
@ -34,6 +35,7 @@ pub enum ComponentStory {
|
|||||||
impl ComponentStory {
|
impl ComponentStory {
|
||||||
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
|
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
|
||||||
match self {
|
match self {
|
||||||
|
Self::AutoHeightEditor => AutoHeightEditorStory::new(cx).into(),
|
||||||
Self::Avatar => cx.build_view(|_| ui::AvatarStory).into(),
|
Self::Avatar => cx.build_view(|_| ui::AvatarStory).into(),
|
||||||
Self::Button => cx.build_view(|_| ui::ButtonStory).into(),
|
Self::Button => cx.build_view(|_| ui::ButtonStory).into(),
|
||||||
Self::Checkbox => cx.build_view(|_| ui::CheckboxStory).into(),
|
Self::Checkbox => cx.build_view(|_| ui::CheckboxStory).into(),
|
||||||
|
@ -80,7 +80,6 @@ impl Render for Toolbar {
|
|||||||
type Element = Div;
|
type Element = Div;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
//dbg!(&self.items.len());
|
|
||||||
v_stack()
|
v_stack()
|
||||||
.border_b()
|
.border_b()
|
||||||
.border_color(cx.theme().colors().border_variant)
|
.border_color(cx.theme().colors().border_variant)
|
||||||
|
Loading…
Reference in New Issue
Block a user