mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-24 17:28:40 +00:00
Allow editor to be created in auto-height mode
This commit is contained in:
parent
405ff1d9db
commit
54b4a4bf6a
4 changed files with 81 additions and 28 deletions
|
@ -325,6 +325,13 @@ impl SizeConstraint {
|
|||
Axis::Vertical => self.max.y(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min_along(&self, axis: Axis) -> f32 {
|
||||
match axis {
|
||||
Axis::Horizontal => self.min.x(),
|
||||
Axis::Vertical => self.min.y(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for SizeConstraint {
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
use crate::{
|
||||
channel::{Channel, ChannelEvent, ChannelList, ChannelMessage},
|
||||
editor::Editor,
|
||||
Settings,
|
||||
};
|
||||
use gpui::{elements::*, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext};
|
||||
use gpui::{
|
||||
elements::*, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use postage::watch;
|
||||
|
||||
pub struct ChatPanel {
|
||||
channel_list: ModelHandle<ChannelList>,
|
||||
active_channel: Option<(ModelHandle<Channel>, Subscription)>,
|
||||
messages: ListState,
|
||||
input_editor: ViewHandle<Editor>,
|
||||
settings: watch::Receiver<Settings>,
|
||||
}
|
||||
|
||||
|
@ -20,10 +24,12 @@ impl ChatPanel {
|
|||
settings: watch::Receiver<Settings>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let input_editor = cx.add_view(|cx| Editor::auto_height(settings.clone(), cx));
|
||||
let mut this = Self {
|
||||
channel_list,
|
||||
messages: ListState::new(Vec::new()),
|
||||
active_channel: None,
|
||||
messages: ListState::new(Vec::new()),
|
||||
input_editor,
|
||||
settings,
|
||||
};
|
||||
|
||||
|
@ -81,7 +87,7 @@ impl ChatPanel {
|
|||
}
|
||||
|
||||
fn render_active_channel_messages(&self) -> ElementBox {
|
||||
Expanded::new(0.8, List::new(self.messages.clone()).boxed()).boxed()
|
||||
Expanded::new(1., List::new(self.messages.clone()).boxed()).boxed()
|
||||
}
|
||||
|
||||
fn render_message(&self, message: &ChannelMessage) -> ElementBox {
|
||||
|
@ -99,7 +105,9 @@ impl ChatPanel {
|
|||
}
|
||||
|
||||
fn render_input_box(&self) -> ElementBox {
|
||||
Empty::new().boxed()
|
||||
ConstrainedBox::new(ChildView::new(self.input_editor.id()).boxed())
|
||||
.with_max_height(100.)
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ const MAX_LINE_LEN: usize = 1024;
|
|||
action!(Cancel);
|
||||
action!(Backspace);
|
||||
action!(Delete);
|
||||
action!(Newline);
|
||||
action!(Newline, bool);
|
||||
action!(Insert, String);
|
||||
action!(DeleteLine);
|
||||
action!(DeleteToPreviousWordBoundary);
|
||||
|
@ -102,7 +102,8 @@ pub fn init(cx: &mut MutableAppContext) {
|
|||
Binding::new("ctrl-h", Backspace, Some("BufferView")),
|
||||
Binding::new("delete", Delete, Some("BufferView")),
|
||||
Binding::new("ctrl-d", Delete, Some("BufferView")),
|
||||
Binding::new("enter", Newline, Some("BufferView")),
|
||||
Binding::new("enter", Newline(false), Some("BufferView")),
|
||||
Binding::new("alt-enter", Newline(true), Some("BufferView")),
|
||||
Binding::new("tab", Insert("\t".into()), Some("BufferView")),
|
||||
Binding::new("ctrl-shift-K", DeleteLine, Some("BufferView")),
|
||||
Binding::new(
|
||||
|
@ -268,6 +269,12 @@ pub enum SelectPhase {
|
|||
End,
|
||||
}
|
||||
|
||||
enum EditorMode {
|
||||
SingleLine,
|
||||
AutoHeight,
|
||||
Full,
|
||||
}
|
||||
|
||||
pub struct Editor {
|
||||
handle: WeakViewHandle<Self>,
|
||||
buffer: ModelHandle<Buffer>,
|
||||
|
@ -285,12 +292,13 @@ pub struct Editor {
|
|||
cursors_visible: bool,
|
||||
blink_epoch: usize,
|
||||
blinking_paused: bool,
|
||||
single_line: bool,
|
||||
mode: EditorMode,
|
||||
}
|
||||
|
||||
pub struct Snapshot {
|
||||
pub display_snapshot: DisplayMapSnapshot,
|
||||
pub gutter_visible: bool,
|
||||
pub auto_height: bool,
|
||||
pub theme: Arc<Theme>,
|
||||
pub font_family: FamilyId,
|
||||
pub font_size: f32,
|
||||
|
@ -313,7 +321,14 @@ impl Editor {
|
|||
pub fn single_line(settings: watch::Receiver<Settings>, cx: &mut ViewContext<Self>) -> Self {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
|
||||
let mut view = Self::for_buffer(buffer, settings, cx);
|
||||
view.single_line = true;
|
||||
view.mode = EditorMode::SingleLine;
|
||||
view
|
||||
}
|
||||
|
||||
pub fn auto_height(settings: watch::Receiver<Settings>, cx: &mut ViewContext<Self>) -> Self {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
|
||||
let mut view = Self::for_buffer(buffer, settings, cx);
|
||||
view.mode = EditorMode::AutoHeight;
|
||||
view
|
||||
}
|
||||
|
||||
|
@ -359,7 +374,7 @@ impl Editor {
|
|||
cursors_visible: false,
|
||||
blink_epoch: 0,
|
||||
blinking_paused: false,
|
||||
single_line: false,
|
||||
mode: EditorMode::Full,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,7 +391,8 @@ impl Editor {
|
|||
|
||||
Snapshot {
|
||||
display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
|
||||
gutter_visible: !self.single_line,
|
||||
gutter_visible: matches!(self.mode, EditorMode::Full),
|
||||
auto_height: matches!(self.mode, EditorMode::AutoHeight),
|
||||
scroll_position: self.scroll_position,
|
||||
scroll_top_anchor: self.scroll_top_anchor.clone(),
|
||||
theme: settings.theme.clone(),
|
||||
|
@ -413,10 +429,15 @@ impl Editor {
|
|||
line_height: f32,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> bool {
|
||||
let visible_lines = viewport_height / line_height;
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut scroll_position =
|
||||
compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor);
|
||||
let max_scroll_top = display_map.max_point().row().saturating_sub(1) as f32;
|
||||
let max_scroll_top = if matches!(self.mode, EditorMode::AutoHeight) {
|
||||
(display_map.max_point().row() as f32 - visible_lines + 1.).max(0.)
|
||||
} else {
|
||||
display_map.max_point().row().saturating_sub(1) as f32
|
||||
};
|
||||
if scroll_position.y() > max_scroll_top {
|
||||
scroll_position.set_y(max_scroll_top);
|
||||
self.set_scroll_position(scroll_position, cx);
|
||||
|
@ -428,7 +449,6 @@ impl Editor {
|
|||
return false;
|
||||
}
|
||||
|
||||
let visible_lines = viewport_height / line_height;
|
||||
let first_cursor_top = self
|
||||
.selections(cx)
|
||||
.first()
|
||||
|
@ -445,9 +465,13 @@ impl Editor {
|
|||
.row() as f32
|
||||
+ 1.0;
|
||||
|
||||
let margin = ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0)
|
||||
.floor()
|
||||
.min(3.0);
|
||||
let margin = if matches!(self.mode, EditorMode::AutoHeight) {
|
||||
0.
|
||||
} else {
|
||||
((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0)
|
||||
.floor()
|
||||
.min(3.0)
|
||||
};
|
||||
if margin < 0.0 {
|
||||
return false;
|
||||
}
|
||||
|
@ -695,11 +719,17 @@ impl Editor {
|
|||
self.end_transaction(cx);
|
||||
}
|
||||
|
||||
fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
|
||||
if self.single_line {
|
||||
cx.propagate_action();
|
||||
} else {
|
||||
self.insert(&Insert("\n".into()), cx);
|
||||
fn newline(&mut self, Newline(insert_newline): &Newline, cx: &mut ViewContext<Self>) {
|
||||
match self.mode {
|
||||
EditorMode::SingleLine => cx.propagate_action(),
|
||||
EditorMode::AutoHeight => {
|
||||
if *insert_newline {
|
||||
self.insert(&Insert("\n".into()), cx);
|
||||
} else {
|
||||
cx.propagate_action();
|
||||
}
|
||||
}
|
||||
EditorMode::Full => self.insert(&Insert("\n".into()), cx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1276,7 +1306,7 @@ impl Editor {
|
|||
|
||||
pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
if self.single_line {
|
||||
if matches!(self.mode, EditorMode::SingleLine) {
|
||||
cx.propagate_action();
|
||||
} else {
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
|
@ -1317,7 +1347,7 @@ impl Editor {
|
|||
}
|
||||
|
||||
pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
|
||||
if self.single_line {
|
||||
if matches!(self.mode, EditorMode::SingleLine) {
|
||||
cx.propagate_action();
|
||||
} else {
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{DisplayPoint, Editor, Select, SelectPhase, Snapshot, Insert, Scroll};
|
||||
use super::{DisplayPoint, Editor, EditorMode, Insert, Scroll, Select, SelectPhase, Snapshot};
|
||||
use crate::time::ReplicaId;
|
||||
use gpui::{
|
||||
color::Color,
|
||||
|
@ -9,8 +9,8 @@ use gpui::{
|
|||
},
|
||||
json::{self, ToJson},
|
||||
text_layout::{self, TextLayoutCache},
|
||||
AppContext, Border, Element, Event, EventContext, FontCache, LayoutContext, MutableAppContext,
|
||||
PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
|
||||
AppContext, Axis, Border, Element, Event, EventContext, FontCache, LayoutContext,
|
||||
MutableAppContext, PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
|
||||
};
|
||||
use json::json;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -204,7 +204,7 @@ impl EditorElement {
|
|||
corner_radius: 0.,
|
||||
});
|
||||
|
||||
if !editor.single_line {
|
||||
if let EditorMode::Full = editor.mode {
|
||||
let mut active_rows = layout.active_rows.iter().peekable();
|
||||
while let Some((start_row, contains_non_empty_selection)) = active_rows.next() {
|
||||
let mut end_row = *start_row;
|
||||
|
@ -409,8 +409,16 @@ impl Element for EditorElement {
|
|||
snapshot
|
||||
}
|
||||
});
|
||||
if size.y().is_infinite() {
|
||||
size.set_y((snapshot.max_point().row() + 1) as f32 * line_height);
|
||||
|
||||
let scroll_height = (snapshot.max_point().row() + 1) as f32 * line_height;
|
||||
if snapshot.auto_height {
|
||||
size.set_y(
|
||||
scroll_height
|
||||
.min(constraint.max_along(Axis::Vertical))
|
||||
.max(constraint.min_along(Axis::Vertical)),
|
||||
)
|
||||
} else if size.y().is_infinite() {
|
||||
size.set_y(scroll_height);
|
||||
}
|
||||
let gutter_size = vec2f(gutter_width, size.y());
|
||||
let text_size = vec2f(text_width, size.y());
|
||||
|
|
Loading…
Reference in a new issue