project panel: Fix rendering of groups of dragged project panel entries (#20686)
This PR introduces a new parameter for `on_drag` in gpui, which is an offset from the element origin to the mouse event origin. Release Notes: - Fixed rendering of dragged project panel entries
This commit is contained in:
parent
43999c47e1
commit
56c93be4de
5 changed files with 30 additions and 17 deletions
|
@ -2521,7 +2521,7 @@ impl CollabPanel {
|
|||
.flex()
|
||||
.w_full()
|
||||
.when(!channel.is_root_channel(), |el| {
|
||||
el.on_drag(channel.clone(), move |channel, cx| {
|
||||
el.on_drag(channel.clone(), move |channel, _, cx| {
|
||||
cx.new_view(|_| DraggedChannelView {
|
||||
channel: channel.clone(),
|
||||
width,
|
||||
|
|
|
@ -443,7 +443,7 @@ impl Interactivity {
|
|||
pub fn on_drag<T, W>(
|
||||
&mut self,
|
||||
value: T,
|
||||
constructor: impl Fn(&T, &mut WindowContext) -> View<W> + 'static,
|
||||
constructor: impl Fn(&T, Point<Pixels>, &mut WindowContext) -> View<W> + 'static,
|
||||
) where
|
||||
Self: Sized,
|
||||
T: 'static,
|
||||
|
@ -455,7 +455,9 @@ impl Interactivity {
|
|||
);
|
||||
self.drag_listener = Some((
|
||||
Box::new(value),
|
||||
Box::new(move |value, cx| constructor(value.downcast_ref().unwrap(), cx).into()),
|
||||
Box::new(move |value, offset, cx| {
|
||||
constructor(value.downcast_ref().unwrap(), offset, cx).into()
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -966,14 +968,15 @@ pub trait StatefulInteractiveElement: InteractiveElement {
|
|||
|
||||
/// On drag initiation, this callback will be used to create a new view to render the dragged value for a
|
||||
/// drag and drop operation. This API should also be used as the equivalent of 'on drag start' with
|
||||
/// the [`Self::on_drag_move`] API
|
||||
/// the [`Self::on_drag_move`] API.
|
||||
/// The callback also has access to the offset of triggering click from the origin of parent element.
|
||||
/// The fluent API equivalent to [`Interactivity::on_drag`]
|
||||
///
|
||||
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
|
||||
fn on_drag<T, W>(
|
||||
mut self,
|
||||
value: T,
|
||||
constructor: impl Fn(&T, &mut WindowContext) -> View<W> + 'static,
|
||||
constructor: impl Fn(&T, Point<Pixels>, &mut WindowContext) -> View<W> + 'static,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -1056,7 +1059,8 @@ pub(crate) type ScrollWheelListener =
|
|||
|
||||
pub(crate) type ClickListener = Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>;
|
||||
|
||||
pub(crate) type DragListener = Box<dyn Fn(&dyn Any, &mut WindowContext) -> AnyView + 'static>;
|
||||
pub(crate) type DragListener =
|
||||
Box<dyn Fn(&dyn Any, Point<Pixels>, &mut WindowContext) -> AnyView + 'static>;
|
||||
|
||||
type DropListener = Box<dyn Fn(&dyn Any, &mut WindowContext) + 'static>;
|
||||
|
||||
|
@ -1818,7 +1822,8 @@ impl Interactivity {
|
|||
if let Some((drag_value, drag_listener)) = drag_listener.take() {
|
||||
*clicked_state.borrow_mut() = ElementClickedState::default();
|
||||
let cursor_offset = event.position - hitbox.origin;
|
||||
let drag = (drag_listener)(drag_value.as_ref(), cx);
|
||||
let drag =
|
||||
(drag_listener)(drag_value.as_ref(), cursor_offset, cx);
|
||||
cx.active_drag = Some(AnyDrag {
|
||||
view: drag,
|
||||
value: drag_value,
|
||||
|
|
|
@ -240,6 +240,7 @@ struct DraggedProjectEntryView {
|
|||
selection: SelectedEntry,
|
||||
details: EntryDetails,
|
||||
width: Pixels,
|
||||
click_offset: Point<Pixels>,
|
||||
selections: Arc<BTreeSet<SelectedEntry>>,
|
||||
}
|
||||
|
||||
|
@ -2681,10 +2682,11 @@ impl ProjectPanel {
|
|||
},
|
||||
))
|
||||
})
|
||||
.on_drag(dragged_selection, move |selection, cx| {
|
||||
.on_drag(dragged_selection, move |selection, click_offset, cx| {
|
||||
cx.new_view(|_| DraggedProjectEntryView {
|
||||
details: details.clone(),
|
||||
width,
|
||||
click_offset,
|
||||
selection: selection.active_selection,
|
||||
selections: selection.marked_selections.clone(),
|
||||
})
|
||||
|
@ -3559,15 +3561,21 @@ impl Render for DraggedProjectEntryView {
|
|||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let settings = ProjectPanelSettings::get_global(cx);
|
||||
let ui_font = ThemeSettings::get_global(cx).ui_font.clone();
|
||||
|
||||
h_flex().font(ui_font).map(|this| {
|
||||
if self.selections.contains(&self.selection) {
|
||||
this.flex_shrink()
|
||||
if self.selections.len() > 1 && self.selections.contains(&self.selection) {
|
||||
this.flex_none()
|
||||
.w(self.width)
|
||||
.child(div().w(self.click_offset.x))
|
||||
.child(
|
||||
div()
|
||||
.p_1()
|
||||
.items_end()
|
||||
.rounded_md()
|
||||
.child(self.selections.len().to_string())
|
||||
.rounded_xl()
|
||||
.bg(cx.theme().colors().background)
|
||||
.child(Label::new(format!("{} entries", self.selections.len()))),
|
||||
)
|
||||
} else {
|
||||
this.bg(cx.theme().colors().background).w(self.width).child(
|
||||
this.w(self.width).bg(cx.theme().colors().background).child(
|
||||
ListItem::new(self.selection.entry_id.to_proto() as usize)
|
||||
.indent_level(self.details.depth)
|
||||
.indent_step_size(px(settings.indent_size))
|
||||
|
|
|
@ -605,7 +605,7 @@ impl Render for Dock {
|
|||
let create_resize_handle = || {
|
||||
let handle = div()
|
||||
.id("resize-handle")
|
||||
.on_drag(DraggedDock(position), |dock, cx| {
|
||||
.on_drag(DraggedDock(position), |dock, _, cx| {
|
||||
cx.stop_propagation();
|
||||
cx.new_view(|_| dock.clone())
|
||||
})
|
||||
|
|
|
@ -1950,7 +1950,7 @@ impl Pane {
|
|||
is_active,
|
||||
ix,
|
||||
},
|
||||
|tab, cx| cx.new_view(|_| tab.clone()),
|
||||
|tab, _, cx| cx.new_view(|_| tab.clone()),
|
||||
)
|
||||
.drag_over::<DraggedTab>(|tab, _, cx| {
|
||||
tab.bg(cx.theme().colors().drop_target_background)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue