Merge branch 'main' into fix-panel-resize

This commit is contained in:
Max Brunsfeld 2023-12-19 08:55:55 -08:00
commit cf037ea4a8
13 changed files with 131 additions and 95 deletions

View file

@ -962,15 +962,12 @@ impl CollabPanel {
self.entries.push(ListEntry::ContactPlaceholder);
}
self.list_state.reset(self.entries.len());
if select_same_item {
if let Some(prev_selected_entry) = prev_selected_entry {
self.selection.take();
for (ix, entry) in self.entries.iter().enumerate() {
if *entry == prev_selected_entry {
self.selection = Some(ix);
self.scroll_to_item(ix);
break;
}
}
@ -980,49 +977,53 @@ impl CollabPanel {
if self.entries.is_empty() {
None
} else {
let ix = prev_selection.min(self.entries.len() - 1);
self.scroll_to_item(ix);
Some(ix)
Some(prev_selection.min(self.entries.len() - 1))
}
});
}
let old_scroll_top = self.list_state.logical_scroll_top();
self.list_state.reset(self.entries.len());
if scroll_to_top {
self.scroll_to_item(0)
self.list_state.scroll_to(ListOffset::default());
} else {
let ListOffset {
item_ix: old_index,
offset_in_item: old_offset,
} = self.list_state.logical_scroll_top();
// Attempt to maintain the same scroll position.
if let Some(old_top_entry) = old_entries.get(old_index) {
let (new_index, new_offset) = self
if let Some(old_top_entry) = old_entries.get(old_scroll_top.item_ix) {
let new_scroll_top = self
.entries
.iter()
.position(|entry| entry == old_top_entry)
.map(|item_ix| (item_ix, old_offset))
.map(|item_ix| ListOffset {
item_ix,
offset_in_item: old_scroll_top.offset_in_item,
})
.or_else(|| {
let entry_after_old_top = old_entries.get(old_index + 1)?;
let entry_after_old_top = old_entries.get(old_scroll_top.item_ix + 1)?;
let item_ix = self
.entries
.iter()
.position(|entry| entry == entry_after_old_top)?;
Some((item_ix, px(0.)))
Some(ListOffset {
item_ix,
offset_in_item: Pixels::ZERO,
})
})
.or_else(|| {
let entry_before_old_top = old_entries.get(old_index.saturating_sub(1))?;
let entry_before_old_top =
old_entries.get(old_scroll_top.item_ix.saturating_sub(1))?;
let item_ix = self
.entries
.iter()
.position(|entry| entry == entry_before_old_top)?;
Some((item_ix, px(0.)))
})
.unwrap_or_else(|| (old_index, old_offset));
Some(ListOffset {
item_ix,
offset_in_item: Pixels::ZERO,
})
});
self.list_state.scroll_to(ListOffset {
item_ix: new_index,
offset_in_item: new_offset,
});
self.list_state
.scroll_to(new_scroll_top.unwrap_or(old_scroll_top));
}
}

View file

@ -3,11 +3,12 @@ use call::{room, ActiveCall};
use client::User;
use collections::HashMap;
use gpui::{
px, AppContext, Div, Element, ParentElement, Render, RenderOnce, Size, Styled, ViewContext,
VisualContext,
img, px, AppContext, Div, ParentElement, Render, Size, Styled, ViewContext, VisualContext,
};
use settings::Settings;
use std::sync::{Arc, Weak};
use ui::{h_stack, v_stack, Avatar, Button, Clickable, Label};
use theme::ThemeSettings;
use ui::{h_stack, prelude::*, v_stack, Button, Label};
use workspace::AppState;
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
@ -21,8 +22,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
worktree_root_names,
} => {
let window_size = Size {
width: px(380.),
height: px(64.),
width: px(400.),
height: px(96.),
};
for screen in cx.displays() {
@ -116,56 +117,70 @@ impl ProjectSharedNotification {
});
}
}
fn render_owner(&self) -> impl Element {
h_stack()
.child(Avatar::new(self.owner.avatar_uri.clone()))
.child(
v_stack()
.child(Label::new(self.owner.github_login.clone()))
.child(Label::new(format!(
"is sharing a project in Zed{}",
if self.worktree_root_names.is_empty() {
""
} else {
":"
}
)))
.children(if self.worktree_root_names.is_empty() {
None
} else {
Some(Label::new(self.worktree_root_names.join(", ")))
}),
)
}
fn render_buttons(&self, cx: &mut ViewContext<Self>) -> impl Element {
let this = cx.view().clone();
v_stack()
.child(Button::new("open", "Open").render(cx).on_click({
let this = this.clone();
move |_, cx| {
this.update(cx, |this, cx| this.join(cx));
}
}))
.child(
Button::new("dismiss", "Dismiss")
.render(cx)
.on_click(move |_, cx| {
this.update(cx, |this, cx| this.dismiss(cx));
}),
)
}
}
impl Render for ProjectSharedNotification {
type Element = Div;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
// TODO: Is there a better place for us to initialize the font?
let (ui_font, ui_font_size) = {
let theme_settings = ThemeSettings::get_global(cx);
(
theme_settings.ui_font.family.clone(),
theme_settings.ui_font_size.clone(),
)
};
cx.set_rem_size(ui_font_size);
h_stack()
.font(ui_font)
.text_ui()
.justify_between()
.size_full()
.bg(gpui::red())
.child(self.render_owner())
.child(self.render_buttons(cx))
.elevation_3(cx)
.p_2()
.gap_2()
.child(
h_stack()
.gap_2()
.child(
img(self.owner.avatar_uri.clone())
.w_16()
.h_16()
.rounded_full(),
)
.child(
v_stack()
.child(Label::new(self.owner.github_login.clone()))
.child(Label::new(format!(
"is sharing a project in Zed{}",
if self.worktree_root_names.is_empty() {
""
} else {
":"
}
)))
.children(if self.worktree_root_names.is_empty() {
None
} else {
Some(Label::new(self.worktree_root_names.join(", ")))
}),
),
)
.child(
v_stack()
.child(Button::new("open", "Open").on_click(cx.listener(
move |this, _event, cx| {
this.join(cx);
},
)))
.child(Button::new("dismiss", "Dismiss").on_click(cx.listener(
move |this, _event, cx| {
this.dismiss(cx);
},
))),
)
}
}

View file

@ -1351,7 +1351,7 @@ impl EditorElement {
));
}
let mouse_position = cx.mouse_position();
let mut mouse_position = cx.mouse_position();
if track_bounds.contains(&mouse_position) {
cx.set_cursor_style(CursorStyle::Arrow);
}
@ -1377,6 +1377,8 @@ impl EditorElement {
}
editor.set_scroll_position(position, cx);
}
mouse_position = event.position;
cx.stop_propagation();
} else {
editor.scroll_manager.set_is_dragging_scrollbar(false, cx);
@ -1392,6 +1394,10 @@ impl EditorElement {
cx.on_mouse_event({
let editor = self.editor.clone();
move |event: &MouseUpEvent, phase, cx| {
if phase == DispatchPhase::Capture {
return;
}
editor.update(cx, |editor, cx| {
editor.scroll_manager.set_is_dragging_scrollbar(false, cx);
cx.stop_propagation();
@ -1402,6 +1408,10 @@ impl EditorElement {
cx.on_mouse_event({
let editor = self.editor.clone();
move |event: &MouseDownEvent, phase, cx| {
if phase == DispatchPhase::Capture {
return;
}
editor.update(cx, |editor, cx| {
if track_bounds.contains(&event.position) {
editor.scroll_manager.set_is_dragging_scrollbar(true, cx);

View file

@ -567,12 +567,7 @@ impl<'a> VisualTestContext<'a> {
pub fn window_title(&mut self) -> Option<String> {
self.cx
.update_window(self.window, |_, cx| {
cx.window
.platform_window
.as_test()
.unwrap()
.window_title
.clone()
cx.window.platform_window.as_test().unwrap().title.clone()
})
.unwrap()
}

View file

@ -1061,7 +1061,7 @@ impl Interactivity {
{
cx.focus(&focus_handle);
// If there is a parent that is also focusable, prevent it
// from trasferring focus because we already did so.
// from transferring focus because we already did so.
cx.prevent_default();
}
}

View file

@ -293,7 +293,7 @@ impl std::fmt::Debug for ListItem {
}
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Default)]
pub struct ListOffset {
pub item_ix: usize,
pub offset_in_item: Pixels,

View file

@ -21,7 +21,8 @@ pub(crate) struct TestWindowHandlers {
pub struct TestWindow {
pub(crate) bounds: WindowBounds,
display: Rc<dyn PlatformDisplay>,
pub(crate) window_title: Option<String>,
pub(crate) title: Option<String>,
pub(crate) edited: bool,
pub(crate) input_handler: Option<Arc<Mutex<Box<dyn PlatformInputHandler>>>>,
pub(crate) handlers: Arc<Mutex<TestWindowHandlers>>,
platform: Weak<TestPlatform>,
@ -41,7 +42,8 @@ impl TestWindow {
input_handler: None,
sprite_atlas: Arc::new(TestAtlas::new()),
handlers: Default::default(),
window_title: Default::default(),
title: Default::default(),
edited: false,
}
}
}
@ -109,11 +111,11 @@ impl PlatformWindow for TestWindow {
}
fn set_title(&mut self, title: &str) {
self.window_title = Some(title.to_owned());
self.title = Some(title.to_owned());
}
fn set_edited(&mut self, _edited: bool) {
unimplemented!()
fn set_edited(&mut self, edited: bool) {
self.edited = edited;
}
fn show_character_palette(&self) {

View file

@ -773,6 +773,10 @@ impl<'a> WindowContext<'a> {
self.window.platform_window.set_title(title);
}
pub fn set_window_edited(&mut self, edited: bool) {
self.window.platform_window.set_edited(edited);
}
pub fn display(&self) -> Option<Rc<dyn PlatformDisplay>> {
self.platform
.displays()

View file

@ -752,8 +752,7 @@ impl Item for TerminalView {
) -> Task<anyhow::Result<View<Self>>> {
let window = cx.window_handle();
cx.spawn(|pane, mut cx| async move {
let cwd = None;
TERMINAL_DB
let cwd = TERMINAL_DB
.get_working_directory(item_id, workspace_id)
.log_err()
.flatten()

View file

@ -1,4 +1,4 @@
use gpui::{relative, DefiniteLength};
use gpui::{relative, DefiniteLength, MouseButton};
use gpui::{rems, transparent_black, AnyElement, AnyView, ClickEvent, Div, Hsla, Rems, Stateful};
use smallvec::SmallVec;
@ -372,10 +372,11 @@ impl RenderOnce for ButtonLike {
.when_some(
self.on_click.filter(|_| !self.disabled),
|this, on_click| {
this.on_click(move |event, cx| {
cx.stop_propagation();
(on_click)(event, cx)
})
this.on_mouse_down(MouseButton::Left, |_, cx| cx.prevent_default())
.on_click(move |event, cx| {
cx.stop_propagation();
(on_click)(event, cx)
})
},
)
.when_some(self.tooltip, |this, tooltip| {

View file

@ -5,6 +5,7 @@ use crate::StyledExt;
/// Horizontally stacks elements.
///
/// Sets `flex()`, `flex_row()`, `items_center()`
#[track_caller]
pub fn h_stack() -> Div {
div().h_flex()
}
@ -12,6 +13,7 @@ pub fn h_stack() -> Div {
/// Vertically stacks elements.
///
/// Sets `flex()`, `flex_col()`
#[track_caller]
pub fn v_stack() -> Div {
div().v_flex()
}

View file

@ -1493,6 +1493,14 @@ impl Pane {
.on_click(
cx.listener(move |pane: &mut Self, _, cx| pane.activate_item(ix, true, true, cx)),
)
// TODO: This should be a click listener with the middle mouse button instead of a mouse down listener.
.on_mouse_down(
MouseButton::Middle,
cx.listener(move |pane, _event, cx| {
pane.close_item_by_id(item_id, SaveIntent::Close, cx)
.detach_and_log_err(cx);
}),
)
.on_drag(
DraggedTab {
pane: cx.view().clone(),

View file

@ -2520,8 +2520,7 @@ impl Workspace {
.any(|item| item.has_conflict(cx) || item.is_dirty(cx));
if is_edited != self.window_edited {
self.window_edited = is_edited;
// todo!()
// cx.set_window_edited(self.window_edited)
cx.set_window_edited(self.window_edited)
}
}