mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 18:41:56 +03:00
Render a context menu when right-clicking in project panel
It doesn't currently do anything, but I managed to get it rendering in an absolutely positioned way.
This commit is contained in:
parent
f4d13ef596
commit
b110fd5fb7
@ -270,7 +270,7 @@ impl View for AutoUpdateIndicator {
|
|||||||
)
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(|_, cx| cx.dispatch_action(DismissErrorMessage))
|
.on_click(|_, _, cx| cx.dispatch_action(DismissErrorMessage))
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
AutoUpdateStatus::Idle => Empty::new().boxed(),
|
AutoUpdateStatus::Idle => Empty::new().boxed(),
|
||||||
|
@ -320,7 +320,7 @@ impl ChatPanel {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| {
|
.on_click(move |_, _, cx| {
|
||||||
let rpc = rpc.clone();
|
let rpc = rpc.clone();
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
cx.spawn(|mut cx| async move {
|
cx.spawn(|mut cx| async move {
|
||||||
|
@ -302,7 +302,7 @@ impl ContactsPanel {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| cx.dispatch_action(ToggleExpanded(section)))
|
.on_click(move |_, _, cx| cx.dispatch_action(ToggleExpanded(section)))
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ impl ContactsPanel {
|
|||||||
} else {
|
} else {
|
||||||
CursorStyle::Arrow
|
CursorStyle::Arrow
|
||||||
})
|
})
|
||||||
.on_click(move |_, cx| {
|
.on_click(move |_, _, cx| {
|
||||||
if !is_host {
|
if !is_host {
|
||||||
cx.dispatch_global_action(JoinProject {
|
cx.dispatch_global_action(JoinProject {
|
||||||
contact: contact.clone(),
|
contact: contact.clone(),
|
||||||
@ -507,7 +507,7 @@ impl ContactsPanel {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| {
|
.on_click(move |_, _, cx| {
|
||||||
cx.dispatch_action(RespondToContactRequest {
|
cx.dispatch_action(RespondToContactRequest {
|
||||||
user_id,
|
user_id,
|
||||||
accept: false,
|
accept: false,
|
||||||
@ -529,7 +529,7 @@ impl ContactsPanel {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| {
|
.on_click(move |_, _, cx| {
|
||||||
cx.dispatch_action(RespondToContactRequest {
|
cx.dispatch_action(RespondToContactRequest {
|
||||||
user_id,
|
user_id,
|
||||||
accept: true,
|
accept: true,
|
||||||
@ -552,7 +552,7 @@ impl ContactsPanel {
|
|||||||
})
|
})
|
||||||
.with_padding(Padding::uniform(2.))
|
.with_padding(Padding::uniform(2.))
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| cx.dispatch_action(RemoveContact(user_id)))
|
.on_click(move |_, _, cx| cx.dispatch_action(RemoveContact(user_id)))
|
||||||
.flex_float()
|
.flex_float()
|
||||||
.boxed(),
|
.boxed(),
|
||||||
);
|
);
|
||||||
@ -865,7 +865,7 @@ impl View for ContactsPanel {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(|_, cx| cx.dispatch_action(contact_finder::Toggle))
|
.on_click(|_, _, cx| cx.dispatch_action(contact_finder::Toggle))
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
.constrained()
|
.constrained()
|
||||||
@ -913,7 +913,7 @@ impl View for ContactsPanel {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| {
|
.on_click(move |_, _, cx| {
|
||||||
cx.write_to_clipboard(ClipboardItem::new(
|
cx.write_to_clipboard(ClipboardItem::new(
|
||||||
info.url.to_string(),
|
info.url.to_string(),
|
||||||
));
|
));
|
||||||
|
@ -61,7 +61,7 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
|
|||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.with_padding(Padding::uniform(5.))
|
.with_padding(Padding::uniform(5.))
|
||||||
.on_click(move |_, cx| cx.dispatch_any_action(dismiss_action.boxed_clone()))
|
.on_click(move |_, _, cx| cx.dispatch_any_action(dismiss_action.boxed_clone()))
|
||||||
.aligned()
|
.aligned()
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_height(
|
.with_height(
|
||||||
@ -76,13 +76,10 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
|
|||||||
.named("contact notification header"),
|
.named("contact notification header"),
|
||||||
)
|
)
|
||||||
.with_children(body.map(|body| {
|
.with_children(body.map(|body| {
|
||||||
Label::new(
|
Label::new(body.to_string(), theme.body_message.text.clone())
|
||||||
body.to_string(),
|
.contained()
|
||||||
theme.body_message.text.clone(),
|
.with_style(theme.body_message.container)
|
||||||
)
|
.boxed()
|
||||||
.contained()
|
|
||||||
.with_style(theme.body_message.container)
|
|
||||||
.boxed()
|
|
||||||
}))
|
}))
|
||||||
.with_children(if buttons.is_empty() {
|
.with_children(if buttons.is_empty() {
|
||||||
None
|
None
|
||||||
@ -99,7 +96,7 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| cx.dispatch_any_action(action.boxed_clone()))
|
.on_click(move |_, _, cx| cx.dispatch_any_action(action.boxed_clone()))
|
||||||
.boxed()
|
.boxed()
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -159,7 +159,7 @@ impl View for DiagnosticIndicator {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(|_, cx| cx.dispatch_action(crate::Deploy))
|
.on_click(|_, _, cx| cx.dispatch_action(crate::Deploy))
|
||||||
.aligned()
|
.aligned()
|
||||||
.boxed(),
|
.boxed(),
|
||||||
);
|
);
|
||||||
@ -192,7 +192,7 @@ impl View for DiagnosticIndicator {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(|_, cx| cx.dispatch_action(GoToNextDiagnostic))
|
.on_click(|_, _, cx| cx.dispatch_action(GoToNextDiagnostic))
|
||||||
.boxed(),
|
.boxed(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -672,7 +672,7 @@ impl CompletionsMenu {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_mouse_down(move |cx| {
|
.on_mouse_down(move |_, cx| {
|
||||||
cx.dispatch_action(ConfirmCompletion {
|
cx.dispatch_action(ConfirmCompletion {
|
||||||
item_ix: Some(item_ix),
|
item_ix: Some(item_ix),
|
||||||
});
|
});
|
||||||
@ -800,7 +800,7 @@ impl CodeActionsMenu {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_mouse_down(move |cx| {
|
.on_mouse_down(move |_, cx| {
|
||||||
cx.dispatch_action(ConfirmCodeAction {
|
cx.dispatch_action(ConfirmCodeAction {
|
||||||
item_ix: Some(item_ix),
|
item_ix: Some(item_ix),
|
||||||
});
|
});
|
||||||
@ -2590,7 +2590,7 @@ impl Editor {
|
|||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.with_padding(Padding::uniform(3.))
|
.with_padding(Padding::uniform(3.))
|
||||||
.on_mouse_down(|cx| {
|
.on_mouse_down(|_, cx| {
|
||||||
cx.dispatch_action(ToggleCodeActions {
|
cx.dispatch_action(ToggleCodeActions {
|
||||||
deployed_from_indicator: true,
|
deployed_from_indicator: true,
|
||||||
});
|
});
|
||||||
|
@ -612,7 +612,10 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let mut list = List::new(state.clone());
|
let mut list = List::new(state.clone());
|
||||||
let (size, _) = list.layout(constraint, &mut presenter.build_layout_context(false, cx));
|
let (size, _) = list.layout(
|
||||||
|
constraint,
|
||||||
|
&mut presenter.build_layout_context(vec2f(100., 40.), false, cx),
|
||||||
|
);
|
||||||
assert_eq!(size, vec2f(100., 40.));
|
assert_eq!(size, vec2f(100., 40.));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state.0.borrow().items.summary().clone(),
|
state.0.borrow().items.summary().clone(),
|
||||||
@ -634,8 +637,10 @@ mod tests {
|
|||||||
true,
|
true,
|
||||||
&mut presenter.build_event_context(cx),
|
&mut presenter.build_event_context(cx),
|
||||||
);
|
);
|
||||||
let (_, logical_scroll_top) =
|
let (_, logical_scroll_top) = list.layout(
|
||||||
list.layout(constraint, &mut presenter.build_layout_context(false, cx));
|
constraint,
|
||||||
|
&mut presenter.build_layout_context(vec2f(100., 40.), false, cx),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
logical_scroll_top,
|
logical_scroll_top,
|
||||||
ListOffset {
|
ListOffset {
|
||||||
@ -659,8 +664,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let (size, logical_scroll_top) =
|
let (size, logical_scroll_top) = list.layout(
|
||||||
list.layout(constraint, &mut presenter.build_layout_context(false, cx));
|
constraint,
|
||||||
|
&mut presenter.build_layout_context(vec2f(100., 40.), false, cx),
|
||||||
|
);
|
||||||
assert_eq!(size, vec2f(100., 40.));
|
assert_eq!(size, vec2f(100., 40.));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state.0.borrow().items.summary().clone(),
|
state.0.borrow().items.summary().clone(),
|
||||||
@ -770,11 +777,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut list = List::new(state.clone());
|
let mut list = List::new(state.clone());
|
||||||
|
let window_size = vec2f(width, height);
|
||||||
let (size, logical_scroll_top) = list.layout(
|
let (size, logical_scroll_top) = list.layout(
|
||||||
SizeConstraint::new(vec2f(0., 0.), vec2f(width, height)),
|
SizeConstraint::new(vec2f(0., 0.), window_size),
|
||||||
&mut presenter.build_layout_context(false, cx),
|
&mut presenter.build_layout_context(window_size, false, cx),
|
||||||
);
|
);
|
||||||
assert_eq!(size, vec2f(width, height));
|
assert_eq!(size, window_size);
|
||||||
last_logical_scroll_top = Some(logical_scroll_top);
|
last_logical_scroll_top = Some(logical_scroll_top);
|
||||||
|
|
||||||
let state = state.0.borrow();
|
let state = state.0.borrow();
|
||||||
|
@ -14,9 +14,11 @@ pub struct MouseEventHandler {
|
|||||||
state: ElementStateHandle<MouseState>,
|
state: ElementStateHandle<MouseState>,
|
||||||
child: ElementBox,
|
child: ElementBox,
|
||||||
cursor_style: Option<CursorStyle>,
|
cursor_style: Option<CursorStyle>,
|
||||||
mouse_down_handler: Option<Box<dyn FnMut(&mut EventContext)>>,
|
mouse_down_handler: Option<Box<dyn FnMut(Vector2F, &mut EventContext)>>,
|
||||||
click_handler: Option<Box<dyn FnMut(usize, &mut EventContext)>>,
|
click_handler: Option<Box<dyn FnMut(Vector2F, usize, &mut EventContext)>>,
|
||||||
drag_handler: Option<Box<dyn FnMut(Vector2F, &mut EventContext)>>,
|
drag_handler: Option<Box<dyn FnMut(Vector2F, &mut EventContext)>>,
|
||||||
|
right_mouse_down_handler: Option<Box<dyn FnMut(Vector2F, &mut EventContext)>>,
|
||||||
|
right_click_handler: Option<Box<dyn FnMut(Vector2F, usize, &mut EventContext)>>,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ pub struct MouseEventHandler {
|
|||||||
pub struct MouseState {
|
pub struct MouseState {
|
||||||
pub hovered: bool,
|
pub hovered: bool,
|
||||||
pub clicked: bool,
|
pub clicked: bool,
|
||||||
|
pub right_clicked: bool,
|
||||||
prev_drag_position: Option<Vector2F>,
|
prev_drag_position: Option<Vector2F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +46,8 @@ impl MouseEventHandler {
|
|||||||
mouse_down_handler: None,
|
mouse_down_handler: None,
|
||||||
click_handler: None,
|
click_handler: None,
|
||||||
drag_handler: None,
|
drag_handler: None,
|
||||||
|
right_mouse_down_handler: None,
|
||||||
|
right_click_handler: None,
|
||||||
padding: Default::default(),
|
padding: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,12 +57,18 @@ impl MouseEventHandler {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_mouse_down(mut self, handler: impl FnMut(&mut EventContext) + 'static) -> Self {
|
pub fn on_mouse_down(
|
||||||
|
mut self,
|
||||||
|
handler: impl FnMut(Vector2F, &mut EventContext) + 'static,
|
||||||
|
) -> Self {
|
||||||
self.mouse_down_handler = Some(Box::new(handler));
|
self.mouse_down_handler = Some(Box::new(handler));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_click(mut self, handler: impl FnMut(usize, &mut EventContext) + 'static) -> Self {
|
pub fn on_click(
|
||||||
|
mut self,
|
||||||
|
handler: impl FnMut(Vector2F, usize, &mut EventContext) + 'static,
|
||||||
|
) -> Self {
|
||||||
self.click_handler = Some(Box::new(handler));
|
self.click_handler = Some(Box::new(handler));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -67,6 +78,22 @@ impl MouseEventHandler {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_right_mouse_down(
|
||||||
|
mut self,
|
||||||
|
handler: impl FnMut(Vector2F, &mut EventContext) + 'static,
|
||||||
|
) -> Self {
|
||||||
|
self.right_mouse_down_handler = Some(Box::new(handler));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_right_click(
|
||||||
|
mut self,
|
||||||
|
handler: impl FnMut(Vector2F, usize, &mut EventContext) + 'static,
|
||||||
|
) -> Self {
|
||||||
|
self.right_click_handler = Some(Box::new(handler));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_padding(mut self, padding: Padding) -> Self {
|
pub fn with_padding(mut self, padding: Padding) -> Self {
|
||||||
self.padding = padding;
|
self.padding = padding;
|
||||||
self
|
self
|
||||||
@ -120,6 +147,8 @@ impl Element for MouseEventHandler {
|
|||||||
let mouse_down_handler = self.mouse_down_handler.as_mut();
|
let mouse_down_handler = self.mouse_down_handler.as_mut();
|
||||||
let click_handler = self.click_handler.as_mut();
|
let click_handler = self.click_handler.as_mut();
|
||||||
let drag_handler = self.drag_handler.as_mut();
|
let drag_handler = self.drag_handler.as_mut();
|
||||||
|
let right_mouse_down_handler = self.right_mouse_down_handler.as_mut();
|
||||||
|
let right_click_handler = self.right_click_handler.as_mut();
|
||||||
|
|
||||||
let handled_in_child = self.child.dispatch_event(event, cx);
|
let handled_in_child = self.child.dispatch_event(event, cx);
|
||||||
|
|
||||||
@ -144,7 +173,7 @@ impl Element for MouseEventHandler {
|
|||||||
state.prev_drag_position = Some(*position);
|
state.prev_drag_position = Some(*position);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
if let Some(handler) = mouse_down_handler {
|
if let Some(handler) = mouse_down_handler {
|
||||||
handler(cx);
|
handler(*position, cx);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@ -162,7 +191,7 @@ impl Element for MouseEventHandler {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
if let Some(handler) = click_handler {
|
if let Some(handler) = click_handler {
|
||||||
if hit_bounds.contains_point(*position) {
|
if hit_bounds.contains_point(*position) {
|
||||||
handler(*click_count, cx);
|
handler(*position, *click_count, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@ -184,6 +213,36 @@ impl Element for MouseEventHandler {
|
|||||||
handled_in_child
|
handled_in_child
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Event::RightMouseDown { position, .. } => {
|
||||||
|
if !handled_in_child && hit_bounds.contains_point(*position) {
|
||||||
|
state.right_clicked = true;
|
||||||
|
cx.notify();
|
||||||
|
if let Some(handler) = right_mouse_down_handler {
|
||||||
|
handler(*position, cx);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
handled_in_child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::RightMouseUp {
|
||||||
|
position,
|
||||||
|
click_count,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if !handled_in_child && state.right_clicked {
|
||||||
|
state.right_clicked = false;
|
||||||
|
cx.notify();
|
||||||
|
if let Some(handler) = right_click_handler {
|
||||||
|
if hit_bounds.contains_point(*position) {
|
||||||
|
handler(*position, *click_count, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
handled_in_child
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => handled_in_child,
|
_ => handled_in_child,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::{rect::RectF, vector::Vector2F},
|
geometry::{rect::RectF, vector::Vector2F},
|
||||||
|
json::ToJson,
|
||||||
DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
|
DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
|
||||||
SizeConstraint,
|
SizeConstraint,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Overlay {
|
pub struct Overlay {
|
||||||
child: ElementBox,
|
child: ElementBox,
|
||||||
|
abs_position: Option<Vector2F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Overlay {
|
impl Overlay {
|
||||||
pub fn new(child: ElementBox) -> Self {
|
pub fn new(child: ElementBox) -> Self {
|
||||||
Self { child }
|
Self {
|
||||||
|
child,
|
||||||
|
abs_position: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_abs_position(mut self, position: Vector2F) -> Self {
|
||||||
|
self.abs_position = Some(position);
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,6 +35,11 @@ impl Element for Overlay {
|
|||||||
constraint: SizeConstraint,
|
constraint: SizeConstraint,
|
||||||
cx: &mut LayoutContext,
|
cx: &mut LayoutContext,
|
||||||
) -> (Vector2F, Self::LayoutState) {
|
) -> (Vector2F, Self::LayoutState) {
|
||||||
|
let constraint = if self.abs_position.is_some() {
|
||||||
|
SizeConstraint::new(Vector2F::zero(), cx.window_size)
|
||||||
|
} else {
|
||||||
|
constraint
|
||||||
|
};
|
||||||
let size = self.child.layout(constraint, cx);
|
let size = self.child.layout(constraint, cx);
|
||||||
(Vector2F::zero(), size)
|
(Vector2F::zero(), size)
|
||||||
}
|
}
|
||||||
@ -34,9 +51,10 @@ impl Element for Overlay {
|
|||||||
size: &mut Self::LayoutState,
|
size: &mut Self::LayoutState,
|
||||||
cx: &mut PaintContext,
|
cx: &mut PaintContext,
|
||||||
) {
|
) {
|
||||||
let bounds = RectF::new(bounds.origin(), *size);
|
let origin = self.abs_position.unwrap_or(bounds.origin());
|
||||||
|
let visible_bounds = RectF::new(origin, *size);
|
||||||
cx.scene.push_stacking_context(None);
|
cx.scene.push_stacking_context(None);
|
||||||
self.child.paint(bounds.origin(), bounds, cx);
|
self.child.paint(origin, visible_bounds, cx);
|
||||||
cx.scene.pop_stacking_context();
|
cx.scene.pop_stacking_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +77,10 @@ impl Element for Overlay {
|
|||||||
_: &Self::PaintState,
|
_: &Self::PaintState,
|
||||||
cx: &DebugContext,
|
cx: &DebugContext,
|
||||||
) -> serde_json::Value {
|
) -> serde_json::Value {
|
||||||
self.child.debug(cx)
|
json!({
|
||||||
|
"type": "Overlay",
|
||||||
|
"abs_position": self.abs_position.to_json(),
|
||||||
|
"child": self.child.debug(cx),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ pub enum Event {
|
|||||||
},
|
},
|
||||||
RightMouseUp {
|
RightMouseUp {
|
||||||
position: Vector2F,
|
position: Vector2F,
|
||||||
|
click_count: usize,
|
||||||
},
|
},
|
||||||
NavigateMouseDown {
|
NavigateMouseDown {
|
||||||
position: Vector2F,
|
position: Vector2F,
|
||||||
@ -72,7 +73,7 @@ impl Event {
|
|||||||
| Event::LeftMouseUp { position, .. }
|
| Event::LeftMouseUp { position, .. }
|
||||||
| Event::LeftMouseDragged { position }
|
| Event::LeftMouseDragged { position }
|
||||||
| Event::RightMouseDown { position, .. }
|
| Event::RightMouseDown { position, .. }
|
||||||
| Event::RightMouseUp { position }
|
| Event::RightMouseUp { position, .. }
|
||||||
| Event::NavigateMouseDown { position, .. }
|
| Event::NavigateMouseDown { position, .. }
|
||||||
| Event::NavigateMouseUp { position, .. }
|
| Event::NavigateMouseUp { position, .. }
|
||||||
| Event::MouseMoved { position, .. } => Some(*position),
|
| Event::MouseMoved { position, .. } => Some(*position),
|
||||||
|
@ -178,6 +178,7 @@ impl Event {
|
|||||||
native_event.locationInWindow().x as f32,
|
native_event.locationInWindow().x as f32,
|
||||||
window_height - native_event.locationInWindow().y as f32,
|
window_height - native_event.locationInWindow().y as f32,
|
||||||
),
|
),
|
||||||
|
click_count: native_event.clickCount() as usize,
|
||||||
}),
|
}),
|
||||||
NSEventType::NSOtherMouseDown => {
|
NSEventType::NSOtherMouseDown => {
|
||||||
let direction = match native_event.buttonNumber() {
|
let direction = match native_event.buttonNumber() {
|
||||||
|
@ -134,15 +134,16 @@ impl Presenter {
|
|||||||
scene
|
scene
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(&mut self, size: Vector2F, refreshing: bool, cx: &mut MutableAppContext) {
|
fn layout(&mut self, window_size: Vector2F, refreshing: bool, cx: &mut MutableAppContext) {
|
||||||
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
||||||
self.build_layout_context(refreshing, cx)
|
self.build_layout_context(window_size, refreshing, cx)
|
||||||
.layout(root_view_id, SizeConstraint::strict(size));
|
.layout(root_view_id, SizeConstraint::strict(window_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_layout_context<'a>(
|
pub fn build_layout_context<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
|
window_size: Vector2F,
|
||||||
refreshing: bool,
|
refreshing: bool,
|
||||||
cx: &'a mut MutableAppContext,
|
cx: &'a mut MutableAppContext,
|
||||||
) -> LayoutContext<'a> {
|
) -> LayoutContext<'a> {
|
||||||
@ -150,6 +151,7 @@ impl Presenter {
|
|||||||
rendered_views: &mut self.rendered_views,
|
rendered_views: &mut self.rendered_views,
|
||||||
parents: &mut self.parents,
|
parents: &mut self.parents,
|
||||||
refreshing,
|
refreshing,
|
||||||
|
window_size,
|
||||||
font_cache: &self.font_cache,
|
font_cache: &self.font_cache,
|
||||||
font_system: cx.platform().fonts(),
|
font_system: cx.platform().fonts(),
|
||||||
text_layout_cache: &self.text_layout_cache,
|
text_layout_cache: &self.text_layout_cache,
|
||||||
@ -259,6 +261,7 @@ pub struct LayoutContext<'a> {
|
|||||||
parents: &'a mut HashMap<usize, usize>,
|
parents: &'a mut HashMap<usize, usize>,
|
||||||
view_stack: Vec<usize>,
|
view_stack: Vec<usize>,
|
||||||
pub refreshing: bool,
|
pub refreshing: bool,
|
||||||
|
pub window_size: Vector2F,
|
||||||
pub font_cache: &'a Arc<FontCache>,
|
pub font_cache: &'a Arc<FontCache>,
|
||||||
pub font_system: Arc<dyn FontSystem>,
|
pub font_system: Arc<dyn FontSystem>,
|
||||||
pub text_layout_cache: &'a TextLayoutCache,
|
pub text_layout_cache: &'a TextLayoutCache,
|
||||||
|
@ -119,7 +119,7 @@ impl View for Select {
|
|||||||
.with_style(style.header)
|
.with_style(style.header)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |_, cx| cx.dispatch_action(ToggleSelect))
|
.on_click(move |_, _, cx| cx.dispatch_action(ToggleSelect))
|
||||||
.boxed(),
|
.boxed(),
|
||||||
);
|
);
|
||||||
if self.is_open {
|
if self.is_open {
|
||||||
@ -153,7 +153,9 @@ impl View for Select {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.on_click(move |_, cx| cx.dispatch_action(SelectItem(ix)))
|
.on_click(move |_, _, cx| {
|
||||||
|
cx.dispatch_action(SelectItem(ix))
|
||||||
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
@ -90,7 +90,7 @@ impl<D: PickerDelegate> View for Picker<D> {
|
|||||||
.read(cx)
|
.read(cx)
|
||||||
.render_match(ix, state, ix == selected_ix, cx)
|
.render_match(ix, state, ix == selected_ix, cx)
|
||||||
})
|
})
|
||||||
.on_mouse_down(move |cx| cx.dispatch_action(SelectIndex(ix)))
|
.on_mouse_down(move |_, cx| cx.dispatch_action(SelectIndex(ix)))
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.boxed()
|
.boxed()
|
||||||
}));
|
}));
|
||||||
|
@ -4,13 +4,14 @@ use gpui::{
|
|||||||
actions,
|
actions,
|
||||||
anyhow::{anyhow, Result},
|
anyhow::{anyhow, Result},
|
||||||
elements::{
|
elements::{
|
||||||
ChildView, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement,
|
ChildView, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, Overlay, ParentElement,
|
||||||
ScrollTarget, Svg, UniformList, UniformListState,
|
ScrollTarget, Stack, Svg, UniformList, UniformListState,
|
||||||
},
|
},
|
||||||
|
geometry::vector::Vector2F,
|
||||||
impl_internal_actions, keymap,
|
impl_internal_actions, keymap,
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, PromptLevel, Task,
|
AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, PromptLevel,
|
||||||
View, ViewContext, ViewHandle, WeakViewHandle,
|
RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
|
use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
@ -36,6 +37,7 @@ pub struct ProjectPanel {
|
|||||||
selection: Option<Selection>,
|
selection: Option<Selection>,
|
||||||
edit_state: Option<EditState>,
|
edit_state: Option<EditState>,
|
||||||
filename_editor: ViewHandle<Editor>,
|
filename_editor: ViewHandle<Editor>,
|
||||||
|
context_menu: Option<ContextMenu>,
|
||||||
handle: WeakViewHandle<Self>,
|
handle: WeakViewHandle<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +77,17 @@ pub struct Open {
|
|||||||
pub change_focus: bool,
|
pub change_focus: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DeployContextMenu {
|
||||||
|
pub position: Vector2F,
|
||||||
|
pub entry_id: Option<ProjectEntryId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ContextMenu {
|
||||||
|
pub position: Vector2F,
|
||||||
|
pub entry_id: Option<ProjectEntryId>,
|
||||||
|
}
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
project_panel,
|
project_panel,
|
||||||
[
|
[
|
||||||
@ -86,9 +99,10 @@ actions!(
|
|||||||
Rename
|
Rename
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
impl_internal_actions!(project_panel, [Open, ToggleExpanded]);
|
impl_internal_actions!(project_panel, [Open, ToggleExpanded, DeployContextMenu]);
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
|
cx.add_action(ProjectPanel::deploy_context_menu);
|
||||||
cx.add_action(ProjectPanel::expand_selected_entry);
|
cx.add_action(ProjectPanel::expand_selected_entry);
|
||||||
cx.add_action(ProjectPanel::collapse_selected_entry);
|
cx.add_action(ProjectPanel::collapse_selected_entry);
|
||||||
cx.add_action(ProjectPanel::toggle_expanded);
|
cx.add_action(ProjectPanel::toggle_expanded);
|
||||||
@ -156,6 +170,7 @@ impl ProjectPanel {
|
|||||||
selection: None,
|
selection: None,
|
||||||
edit_state: None,
|
edit_state: None,
|
||||||
filename_editor,
|
filename_editor,
|
||||||
|
context_menu: None,
|
||||||
handle: cx.weak_handle(),
|
handle: cx.weak_handle(),
|
||||||
};
|
};
|
||||||
this.update_visible_entries(None, cx);
|
this.update_visible_entries(None, cx);
|
||||||
@ -195,6 +210,14 @@ impl ProjectPanel {
|
|||||||
project_panel
|
project_panel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deploy_context_menu(&mut self, action: &DeployContextMenu, cx: &mut ViewContext<Self>) {
|
||||||
|
self.context_menu = Some(ContextMenu {
|
||||||
|
position: action.position,
|
||||||
|
entry_id: action.entry_id,
|
||||||
|
});
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
fn expand_selected_entry(&mut self, _: &ExpandSelectedEntry, cx: &mut ViewContext<Self>) {
|
fn expand_selected_entry(&mut self, _: &ExpandSelectedEntry, cx: &mut ViewContext<Self>) {
|
||||||
if let Some((worktree, entry)) = self.selected_entry(cx) {
|
if let Some((worktree, entry)) = self.selected_entry(cx) {
|
||||||
let expanded_dir_ids =
|
let expanded_dir_ids =
|
||||||
@ -841,7 +864,7 @@ impl ProjectPanel {
|
|||||||
.with_padding_left(padding)
|
.with_padding_left(padding)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |click_count, cx| {
|
.on_click(move |_, click_count, cx| {
|
||||||
if kind == EntryKind::Dir {
|
if kind == EntryKind::Dir {
|
||||||
cx.dispatch_action(ToggleExpanded(entry_id))
|
cx.dispatch_action(ToggleExpanded(entry_id))
|
||||||
} else {
|
} else {
|
||||||
@ -851,9 +874,33 @@ impl ProjectPanel {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.on_right_mouse_down(move |position, cx| {
|
||||||
|
cx.dispatch_action(DeployContextMenu {
|
||||||
|
entry_id: Some(entry_id),
|
||||||
|
position,
|
||||||
|
})
|
||||||
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_context_menu(&self, cx: &mut RenderContext<Self>) -> Option<ElementBox> {
|
||||||
|
self.context_menu.as_ref().map(|menu| {
|
||||||
|
let style = &cx.global::<Settings>().theme.project_panel.context_menu;
|
||||||
|
|
||||||
|
Overlay::new(
|
||||||
|
Flex::column()
|
||||||
|
.with_child(Label::new("Add File".to_string(), style.label.clone()).boxed())
|
||||||
|
.contained()
|
||||||
|
.with_style(style.container)
|
||||||
|
// .constrained()
|
||||||
|
// .with_width(style.width)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_abs_position(menu.position)
|
||||||
|
.named("Project Panel Context Menu")
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for ProjectPanel {
|
impl View for ProjectPanel {
|
||||||
@ -866,33 +913,38 @@ impl View for ProjectPanel {
|
|||||||
let mut container_style = theme.container;
|
let mut container_style = theme.container;
|
||||||
let padding = std::mem::take(&mut container_style.padding);
|
let padding = std::mem::take(&mut container_style.padding);
|
||||||
let handle = self.handle.clone();
|
let handle = self.handle.clone();
|
||||||
UniformList::new(
|
Stack::new()
|
||||||
self.list.clone(),
|
.with_child(
|
||||||
self.visible_entries
|
UniformList::new(
|
||||||
.iter()
|
self.list.clone(),
|
||||||
.map(|(_, worktree_entries)| worktree_entries.len())
|
self.visible_entries
|
||||||
.sum(),
|
.iter()
|
||||||
move |range, items, cx| {
|
.map(|(_, worktree_entries)| worktree_entries.len())
|
||||||
let theme = cx.global::<Settings>().theme.clone();
|
.sum(),
|
||||||
let this = handle.upgrade(cx).unwrap();
|
move |range, items, cx| {
|
||||||
this.update(cx.app, |this, cx| {
|
let theme = cx.global::<Settings>().theme.clone();
|
||||||
this.for_each_visible_entry(range.clone(), cx, |id, details, cx| {
|
let this = handle.upgrade(cx).unwrap();
|
||||||
items.push(Self::render_entry(
|
this.update(cx.app, |this, cx| {
|
||||||
id,
|
this.for_each_visible_entry(range.clone(), cx, |id, details, cx| {
|
||||||
details,
|
items.push(Self::render_entry(
|
||||||
&this.filename_editor,
|
id,
|
||||||
&theme.project_panel,
|
details,
|
||||||
cx,
|
&this.filename_editor,
|
||||||
));
|
&theme.project_panel,
|
||||||
});
|
cx,
|
||||||
})
|
));
|
||||||
},
|
});
|
||||||
)
|
})
|
||||||
.with_padding_top(padding.top)
|
},
|
||||||
.with_padding_bottom(padding.bottom)
|
)
|
||||||
.contained()
|
.with_padding_top(padding.top)
|
||||||
.with_style(container_style)
|
.with_padding_bottom(padding.bottom)
|
||||||
.boxed()
|
.contained()
|
||||||
|
.with_style(container_style)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_children(self.render_context_menu(cx))
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keymap_context(&self, _: &AppContext) -> keymap::Context {
|
fn keymap_context(&self, _: &AppContext) -> keymap::Context {
|
||||||
|
@ -290,7 +290,7 @@ impl BufferSearchBar {
|
|||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |_, cx| cx.dispatch_action(ToggleSearchOption(search_option)))
|
.on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption(search_option)))
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
@ -314,7 +314,7 @@ impl BufferSearchBar {
|
|||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |_, cx| match direction {
|
.on_click(move |_, _, cx| match direction {
|
||||||
Direction::Prev => cx.dispatch_action(SelectPrevMatch),
|
Direction::Prev => cx.dispatch_action(SelectPrevMatch),
|
||||||
Direction::Next => cx.dispatch_action(SelectNextMatch),
|
Direction::Next => cx.dispatch_action(SelectNextMatch),
|
||||||
})
|
})
|
||||||
|
@ -672,7 +672,7 @@ impl ProjectSearchBar {
|
|||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |_, cx| match direction {
|
.on_click(move |_, _, cx| match direction {
|
||||||
Direction::Prev => cx.dispatch_action(SelectPrevMatch),
|
Direction::Prev => cx.dispatch_action(SelectPrevMatch),
|
||||||
Direction::Next => cx.dispatch_action(SelectNextMatch),
|
Direction::Next => cx.dispatch_action(SelectNextMatch),
|
||||||
})
|
})
|
||||||
@ -699,7 +699,7 @@ impl ProjectSearchBar {
|
|||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |_, cx| cx.dispatch_action(ToggleSearchOption(option)))
|
.on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption(option)))
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
@ -226,6 +226,7 @@ pub struct ProjectPanel {
|
|||||||
pub ignored_entry_fade: f32,
|
pub ignored_entry_fade: f32,
|
||||||
pub filename_editor: FieldEditor,
|
pub filename_editor: FieldEditor,
|
||||||
pub indent_width: f32,
|
pub indent_width: f32,
|
||||||
|
pub context_menu: ContextMenu,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default)]
|
||||||
@ -239,6 +240,14 @@ pub struct ProjectPanelEntry {
|
|||||||
pub icon_spacing: f32,
|
pub icon_spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Default)]
|
||||||
|
pub struct ContextMenu {
|
||||||
|
pub width: f32,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub container: ContainerStyle,
|
||||||
|
pub label: TextStyle,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Default)]
|
#[derive(Debug, Deserialize, Default)]
|
||||||
pub struct CommandPalette {
|
pub struct CommandPalette {
|
||||||
pub key: Interactive<ContainedLabel>,
|
pub key: Interactive<ContainedLabel>,
|
||||||
|
@ -168,7 +168,8 @@ impl View for LspStatus {
|
|||||||
self.failed.join(", "),
|
self.failed.join(", "),
|
||||||
if self.failed.len() > 1 { "s" } else { "" }
|
if self.failed.len() > 1 { "s" } else { "" }
|
||||||
);
|
);
|
||||||
handler = Some(|_, cx: &mut EventContext| cx.dispatch_action(DismissErrorMessage));
|
handler =
|
||||||
|
Some(|_, _, cx: &mut EventContext| cx.dispatch_action(DismissErrorMessage));
|
||||||
} else {
|
} else {
|
||||||
return Empty::new().boxed();
|
return Empty::new().boxed();
|
||||||
}
|
}
|
||||||
|
@ -788,7 +788,7 @@ impl Pane {
|
|||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click({
|
.on_click({
|
||||||
let pane = pane.clone();
|
let pane = pane.clone();
|
||||||
move |_, cx| {
|
move |_, _, cx| {
|
||||||
cx.dispatch_action(CloseItem {
|
cx.dispatch_action(CloseItem {
|
||||||
item_id,
|
item_id,
|
||||||
pane: pane.clone(),
|
pane: pane.clone(),
|
||||||
|
@ -293,7 +293,7 @@ impl View for SidebarButtons {
|
|||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| {
|
.on_click(move |_, _, cx| {
|
||||||
cx.dispatch_action(ToggleSidebarItem {
|
cx.dispatch_action(ToggleSidebarItem {
|
||||||
side,
|
side,
|
||||||
item_index: ix,
|
item_index: ix,
|
||||||
|
@ -1730,7 +1730,7 @@ impl Workspace {
|
|||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(|_, cx| cx.dispatch_action(Authenticate))
|
.on_click(|_, _, cx| cx.dispatch_action(Authenticate))
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.aligned()
|
.aligned()
|
||||||
.boxed(),
|
.boxed(),
|
||||||
@ -1781,7 +1781,7 @@ impl Workspace {
|
|||||||
if let Some(peer_id) = peer_id {
|
if let Some(peer_id) = peer_id {
|
||||||
MouseEventHandler::new::<ToggleFollow, _, _>(replica_id.into(), cx, move |_, _| content)
|
MouseEventHandler::new::<ToggleFollow, _, _>(replica_id.into(), cx, move |_, _| content)
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(move |_, cx| cx.dispatch_action(ToggleFollow(peer_id)))
|
.on_click(move |_, _, cx| cx.dispatch_action(ToggleFollow(peer_id)))
|
||||||
.boxed()
|
.boxed()
|
||||||
} else {
|
} else {
|
||||||
content
|
content
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Theme from "../themes/common/theme";
|
import Theme from "../themes/common/theme";
|
||||||
import { panel } from "./app";
|
import { panel } from "./app";
|
||||||
import { backgroundColor, iconColor, player, text } from "./components";
|
import { backgroundColor, iconColor, player, shadow, text } from "./components";
|
||||||
|
|
||||||
export default function projectPanel(theme: Theme) {
|
export default function projectPanel(theme: Theme) {
|
||||||
return {
|
return {
|
||||||
@ -32,5 +32,19 @@ export default function projectPanel(theme: Theme) {
|
|||||||
text: text(theme, "mono", "primary", { size: "sm" }),
|
text: text(theme, "mono", "primary", { size: "sm" }),
|
||||||
selection: player(theme, 1).selection,
|
selection: player(theme, 1).selection,
|
||||||
},
|
},
|
||||||
|
contextMenu: {
|
||||||
|
width: 100,
|
||||||
|
// background: "#ff0000",
|
||||||
|
background: backgroundColor(theme, 300, "base"),
|
||||||
|
cornerRadius: 6,
|
||||||
|
padding: {
|
||||||
|
bottom: 2,
|
||||||
|
left: 6,
|
||||||
|
right: 6,
|
||||||
|
top: 2,
|
||||||
|
},
|
||||||
|
label: text(theme, "sans", "secondary", { size: "sm" }),
|
||||||
|
shadow: shadow(theme),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user