Merge branch 'main' into collab-panel

This commit is contained in:
Mikayla 2023-08-15 03:25:45 -07:00
commit 111e17b220
No known key found for this signature in database
54 changed files with 1233 additions and 679 deletions

View File

@ -318,7 +318,7 @@ impl View for ActivityIndicator {
on_click, on_click,
} = self.content_to_render(cx); } = self.content_to_render(cx);
let mut element = MouseEventHandler::<Self, _>::new(0, cx, |state, cx| { let mut element = MouseEventHandler::new::<Self, _>(0, cx, |state, cx| {
let theme = &theme::current(cx).workspace.status_bar.lsp_status; let theme = &theme::current(cx).workspace.status_bar.lsp_status;
let style = if state.hovered() && on_click.is_some() { let style = if state.hovered() && on_click.is_some() {
theme.hovered.as_ref().unwrap_or(&theme.default) theme.hovered.as_ref().unwrap_or(&theme.default)

View File

@ -349,7 +349,7 @@ impl AssistantPanel {
enum History {} enum History {}
let theme = theme::current(cx); let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
MouseEventHandler::<History, _>::new(0, cx, |state, _| { MouseEventHandler::new::<History, _>(0, cx, |state, _| {
let style = theme.assistant.hamburger_button.style_for(state); let style = theme.assistant.hamburger_button.style_for(state);
Svg::for_style(style.icon.clone()) Svg::for_style(style.icon.clone())
.contained() .contained()
@ -381,7 +381,7 @@ impl AssistantPanel {
fn render_split_button(cx: &mut ViewContext<Self>) -> impl Element<Self> { fn render_split_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
let theme = theme::current(cx); let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
MouseEventHandler::<Split, _>::new(0, cx, |state, _| { MouseEventHandler::new::<Split, _>(0, cx, |state, _| {
let style = theme.assistant.split_button.style_for(state); let style = theme.assistant.split_button.style_for(state);
Svg::for_style(style.icon.clone()) Svg::for_style(style.icon.clone())
.contained() .contained()
@ -405,7 +405,7 @@ impl AssistantPanel {
fn render_assist_button(cx: &mut ViewContext<Self>) -> impl Element<Self> { fn render_assist_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
let theme = theme::current(cx); let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
MouseEventHandler::<Assist, _>::new(0, cx, |state, _| { MouseEventHandler::new::<Assist, _>(0, cx, |state, _| {
let style = theme.assistant.assist_button.style_for(state); let style = theme.assistant.assist_button.style_for(state);
Svg::for_style(style.icon.clone()) Svg::for_style(style.icon.clone())
.contained() .contained()
@ -423,7 +423,7 @@ impl AssistantPanel {
fn render_quote_button(cx: &mut ViewContext<Self>) -> impl Element<Self> { fn render_quote_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
let theme = theme::current(cx); let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
MouseEventHandler::<QuoteSelection, _>::new(0, cx, |state, _| { MouseEventHandler::new::<QuoteSelection, _>(0, cx, |state, _| {
let style = theme.assistant.quote_button.style_for(state); let style = theme.assistant.quote_button.style_for(state);
Svg::for_style(style.icon.clone()) Svg::for_style(style.icon.clone())
.contained() .contained()
@ -451,7 +451,7 @@ impl AssistantPanel {
fn render_plus_button(cx: &mut ViewContext<Self>) -> impl Element<Self> { fn render_plus_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
let theme = theme::current(cx); let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
MouseEventHandler::<NewConversation, _>::new(0, cx, |state, _| { MouseEventHandler::new::<NewConversation, _>(0, cx, |state, _| {
let style = theme.assistant.plus_button.style_for(state); let style = theme.assistant.plus_button.style_for(state);
Svg::for_style(style.icon.clone()) Svg::for_style(style.icon.clone())
.contained() .contained()
@ -481,7 +481,7 @@ impl AssistantPanel {
&theme.assistant.zoom_in_button &theme.assistant.zoom_in_button
}; };
MouseEventHandler::<ToggleZoomButton, _>::new(0, cx, |state, _| { MouseEventHandler::new::<ToggleZoomButton, _>(0, cx, |state, _| {
let style = style.style_for(state); let style = style.style_for(state);
Svg::for_style(style.icon.clone()) Svg::for_style(style.icon.clone())
.contained() .contained()
@ -507,7 +507,7 @@ impl AssistantPanel {
) -> impl Element<Self> { ) -> impl Element<Self> {
let conversation = &self.saved_conversations[index]; let conversation = &self.saved_conversations[index];
let path = conversation.path.clone(); let path = conversation.path.clone();
MouseEventHandler::<SavedConversationMetadata, _>::new(index, cx, move |state, cx| { MouseEventHandler::new::<SavedConversationMetadata, _>(index, cx, move |state, cx| {
let style = &theme::current(cx).assistant.saved_conversation; let style = &theme::current(cx).assistant.saved_conversation;
Flex::row() Flex::row()
.with_child( .with_child(
@ -1821,7 +1821,7 @@ impl ConversationEditor {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = &theme.assistant; let style = &theme.assistant;
let message_id = message.id; let message_id = message.id;
let sender = MouseEventHandler::<Sender, _>::new( let sender = MouseEventHandler::new::<Sender, _>(
message_id.0, message_id.0,
cx, cx,
|state, _| match message.role { |state, _| match message.role {
@ -2047,7 +2047,7 @@ impl ConversationEditor {
) -> impl Element<Self> { ) -> impl Element<Self> {
enum Model {} enum Model {}
MouseEventHandler::<Model, _>::new(0, cx, |state, cx| { MouseEventHandler::new::<Model, _>(0, cx, |state, cx| {
let style = style.model.style_for(state); let style = style.model.style_for(state);
Label::new(self.conversation.read(cx).model.clone(), style.text.clone()) Label::new(self.conversation.read(cx).model.clone(), style.text.clone())
.contained() .contained()

View File

@ -31,7 +31,7 @@ impl View for UpdateNotification {
let app_name = cx.global::<ReleaseChannel>().display_name(); let app_name = cx.global::<ReleaseChannel>().display_name();
MouseEventHandler::<ViewReleaseNotes, _>::new(0, cx, |state, cx| { MouseEventHandler::new::<ViewReleaseNotes, _>(0, cx, |state, cx| {
Flex::column() Flex::column()
.with_child( .with_child(
Flex::row() Flex::row()
@ -48,7 +48,7 @@ impl View for UpdateNotification {
.flex(1., true), .flex(1., true),
) )
.with_child( .with_child(
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| { MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
let style = theme.dismiss_button.style_for(state); let style = theme.dismiss_button.style_for(state);
Svg::new("icons/x_mark_8.svg") Svg::new("icons/x_mark_8.svg")
.with_color(style.color) .with_color(style.color)

View File

@ -82,7 +82,7 @@ impl View for Breadcrumbs {
.into_any(); .into_any();
} }
MouseEventHandler::<Breadcrumbs, Breadcrumbs>::new(0, cx, |state, _| { MouseEventHandler::new::<Breadcrumbs, _>(0, cx, |state, _| {
let style = style.style_for(state); let style = style.style_for(state);
crumbs.with_style(style.container) crumbs.with_style(style.container)
}) })

View File

@ -7952,7 +7952,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, edits_made, inlay_cache.version(),
edits_made,
"Host editor update the cache version after every cache/view change", "Host editor update the cache version after every cache/view change",
); );
}); });
@ -7975,7 +7976,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, edits_made, inlay_cache.version(),
edits_made,
"Guest editor update the cache version after every cache/view change" "Guest editor update the cache version after every cache/view change"
); );
}); });
@ -7995,7 +7997,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
"Host should get hints from the 1st edit and 1st LSP query" "Host should get hints from the 1st edit and 1st LSP query"
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!(inlay_cache.version, edits_made); assert_eq!(inlay_cache.version(), edits_made);
}); });
editor_b.update(cx_b, |editor, _| { editor_b.update(cx_b, |editor, _| {
assert_eq!( assert_eq!(
@ -8009,7 +8011,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
"Guest should get hints the 1st edit and 2nd LSP query" "Guest should get hints the 1st edit and 2nd LSP query"
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!(inlay_cache.version, edits_made); assert_eq!(inlay_cache.version(), edits_made);
}); });
editor_a.update(cx_a, |editor, cx| { editor_a.update(cx_a, |editor, cx| {
@ -8034,7 +8036,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
4th query was made by guest (but not applied) due to cache invalidation logic" 4th query was made by guest (but not applied) due to cache invalidation logic"
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!(inlay_cache.version, edits_made); assert_eq!(inlay_cache.version(), edits_made);
}); });
editor_b.update(cx_b, |editor, _| { editor_b.update(cx_b, |editor, _| {
assert_eq!( assert_eq!(
@ -8050,7 +8052,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
"Guest should get hints from 3rd edit, 6th LSP query" "Guest should get hints from 3rd edit, 6th LSP query"
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!(inlay_cache.version, edits_made); assert_eq!(inlay_cache.version(), edits_made);
}); });
fake_language_server fake_language_server
@ -8076,7 +8078,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, edits_made, inlay_cache.version(),
edits_made,
"Host should accepted all edits and bump its cache version every time" "Host should accepted all edits and bump its cache version every time"
); );
}); });
@ -8097,7 +8100,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, inlay_cache.version(),
edits_made, edits_made,
"Guest should accepted all edits and bump its cache version every time" "Guest should accepted all edits and bump its cache version every time"
); );
@ -8263,7 +8266,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, 0, inlay_cache.version(),
0,
"Host should not increment its cache version due to no changes", "Host should not increment its cache version due to no changes",
); );
}); });
@ -8278,7 +8282,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, edits_made, inlay_cache.version(),
edits_made,
"Guest editor update the cache version after every cache/view change" "Guest editor update the cache version after every cache/view change"
); );
}); });
@ -8295,7 +8300,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, 0, inlay_cache.version(),
0,
"Host should not increment its cache version due to no changes", "Host should not increment its cache version due to no changes",
); );
}); });
@ -8310,7 +8316,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
); );
let inlay_cache = editor.inlay_hint_cache(); let inlay_cache = editor.inlay_hint_cache();
assert_eq!( assert_eq!(
inlay_cache.version, edits_made, inlay_cache.version(),
edits_made,
"Guest should accepted all edits and bump its cache version every time" "Guest should accepted all edits and bump its cache version every time"
); );
}); });
@ -8318,13 +8325,10 @@ async fn test_inlay_hint_refresh_is_forwarded(
fn extract_hint_labels(editor: &Editor) -> Vec<String> { fn extract_hint_labels(editor: &Editor) -> Vec<String> {
let mut labels = Vec::new(); let mut labels = Vec::new();
for (_, excerpt_hints) in &editor.inlay_hint_cache().hints { for hint in editor.inlay_hint_cache().hints() {
let excerpt_hints = excerpt_hints.read(); match hint.label {
for (_, inlay) in excerpt_hints.hints.iter() { project::InlayHintLabel::String(s) => labels.push(s),
match &inlay.label { _ => unreachable!(),
project::InlayHintLabel::String(s) => labels.push(s.to_string()),
_ => unreachable!(),
}
} }
} }
labels labels

View File

@ -981,7 +981,7 @@ impl CollabPanel {
worktree_root_names.join(", ") worktree_root_names.join(", ")
}; };
MouseEventHandler::<JoinProject, Self>::new(project_id as usize, cx, |mouse_state, _| { MouseEventHandler::new::<JoinProject, _>(project_id as usize, cx, |mouse_state, _| {
let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state); let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state);
let row = theme let row = theme
.project_row .project_row
@ -1075,7 +1075,7 @@ impl CollabPanel {
let baseline_offset = let baseline_offset =
row.name.text.baseline_offset(font_cache) + (theme.row_height - line_height) / 2.; row.name.text.baseline_offset(font_cache) + (theme.row_height - line_height) / 2.;
MouseEventHandler::<OpenSharedScreen, Self>::new( MouseEventHandler::new::<OpenSharedScreen, _>(
peer_id.as_u64() as usize, peer_id.as_u64() as usize,
cx, cx,
|mouse_state, _| { |mouse_state, _| {
@ -1193,7 +1193,7 @@ impl CollabPanel {
enum AddContact {} enum AddContact {}
let button = match section { let button = match section {
Section::ActiveCall => Some( Section::ActiveCall => Some(
MouseEventHandler::<AddContact, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<AddContact, _>(0, cx, |state, _| {
render_icon_button( render_icon_button(
theme theme
.collab_panel .collab_panel
@ -1215,7 +1215,7 @@ impl CollabPanel {
), ),
), ),
Section::Contacts => Some( Section::Contacts => Some(
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<LeaveCallContactList, _>(0, cx, |state, _| {
render_icon_button( render_icon_button(
theme theme
.collab_panel .collab_panel
@ -1237,7 +1237,7 @@ impl CollabPanel {
), ),
), ),
Section::Channels => Some( Section::Channels => Some(
MouseEventHandler::<AddChannel, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<AddChannel, _>(0, cx, |state, _| {
render_icon_button( render_icon_button(
theme theme
.collab_panel .collab_panel
@ -1261,7 +1261,7 @@ impl CollabPanel {
let can_collapse = depth > 0; let can_collapse = depth > 0;
let icon_size = (&theme.collab_panel).section_icon_size; let icon_size = (&theme.collab_panel).section_icon_size;
MouseEventHandler::<Header, Self>::new(section as usize, cx, |state, _| { MouseEventHandler::new::<Header, _>(section as usize, cx, |state, _| {
let header_style = if can_collapse { let header_style = if can_collapse {
theme theme
.collab_panel .collab_panel
@ -1330,7 +1330,7 @@ impl CollabPanel {
let github_login = contact.user.github_login.clone(); let github_login = contact.user.github_login.clone();
let initial_project = project.clone(); let initial_project = project.clone();
let mut event_handler = let mut event_handler =
MouseEventHandler::<Contact, Self>::new(contact.user.id as usize, cx, |state, cx| { MouseEventHandler::new::<Contact, _>(contact.user.id as usize, cx, |state, cx| {
Flex::row() Flex::row()
.with_children(contact.user.avatar.clone().map(|avatar| { .with_children(contact.user.avatar.clone().map(|avatar| {
let status_badge = if contact.online { let status_badge = if contact.online {
@ -1369,7 +1369,7 @@ impl CollabPanel {
.flex(1., true), .flex(1., true),
) )
.with_child( .with_child(
MouseEventHandler::<Cancel, Self>::new( MouseEventHandler::new::<Cancel, _>(
contact.user.id as usize, contact.user.id as usize,
cx, cx,
|mouse_state, _| { |mouse_state, _| {
@ -1421,7 +1421,7 @@ impl CollabPanel {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> AnyElement<Self> { ) -> AnyElement<Self> {
enum AddContacts {} enum AddContacts {}
MouseEventHandler::<AddContacts, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<AddContacts, _>(0, cx, |state, _| {
let style = theme.list_empty_state.style_for(is_selected, state); let style = theme.list_empty_state.style_for(is_selected, state);
Flex::row() Flex::row()
.with_child( .with_child(
@ -1516,7 +1516,7 @@ impl CollabPanel {
const FACEPILE_LIMIT: usize = 4; const FACEPILE_LIMIT: usize = 4;
MouseEventHandler::<Channel, Self>::new(channel.id as usize, cx, |state, cx| { MouseEventHandler::new::<Channel, _>(channel.id as usize, cx, |state, cx| {
Flex::row() Flex::row()
.with_child( .with_child(
Svg::new("icons/hash.svg") Svg::new("icons/hash.svg")
@ -1618,18 +1618,14 @@ impl CollabPanel {
.flex(1., true), .flex(1., true),
) )
.with_child( .with_child(
MouseEventHandler::<Decline, Self>::new( MouseEventHandler::new::<Decline, _>(channel.id as usize, cx, |mouse_state, _| {
channel.id as usize, let button_style = if is_invite_pending {
cx, &theme.disabled_button
|mouse_state, _| { } else {
let button_style = if is_invite_pending { theme.contact_button.style_for(mouse_state)
&theme.disabled_button };
} else { render_icon_button(button_style, "icons/x.svg").aligned()
theme.contact_button.style_for(mouse_state) })
};
render_icon_button(button_style, "icons/x.svg").aligned()
},
)
.with_cursor_style(CursorStyle::PointingHand) .with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, this, cx| { .on_click(MouseButton::Left, move |_, this, cx| {
this.respond_to_channel_invite(channel_id, false, cx); this.respond_to_channel_invite(channel_id, false, cx);
@ -1638,20 +1634,16 @@ impl CollabPanel {
.with_margin_right(button_spacing), .with_margin_right(button_spacing),
) )
.with_child( .with_child(
MouseEventHandler::<Accept, Self>::new( MouseEventHandler::new::<Accept, _>(channel.id as usize, cx, |mouse_state, _| {
channel.id as usize, let button_style = if is_invite_pending {
cx, &theme.disabled_button
|mouse_state, _| { } else {
let button_style = if is_invite_pending { theme.contact_button.style_for(mouse_state)
&theme.disabled_button };
} else { render_icon_button(button_style, "icons/check_8.svg")
theme.contact_button.style_for(mouse_state) .aligned()
}; .flex_float()
render_icon_button(button_style, "icons/check_8.svg") })
.aligned()
.flex_float()
},
)
.with_cursor_style(CursorStyle::PointingHand) .with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, this, cx| { .on_click(MouseButton::Left, move |_, this, cx| {
this.respond_to_channel_invite(channel_id, true, cx); this.respond_to_channel_invite(channel_id, true, cx);
@ -1710,7 +1702,7 @@ impl CollabPanel {
if is_incoming { if is_incoming {
row.add_child( row.add_child(
MouseEventHandler::<Decline, Self>::new(user.id as usize, cx, |mouse_state, _| { MouseEventHandler::new::<Decline, _>(user.id as usize, cx, |mouse_state, _| {
let button_style = if is_contact_request_pending { let button_style = if is_contact_request_pending {
&theme.disabled_button &theme.disabled_button
} else { } else {
@ -1727,7 +1719,7 @@ impl CollabPanel {
); );
row.add_child( row.add_child(
MouseEventHandler::<Accept, Self>::new(user.id as usize, cx, |mouse_state, _| { MouseEventHandler::new::<Accept, _>(user.id as usize, cx, |mouse_state, _| {
let button_style = if is_contact_request_pending { let button_style = if is_contact_request_pending {
&theme.disabled_button &theme.disabled_button
} else { } else {
@ -1744,7 +1736,7 @@ impl CollabPanel {
); );
} else { } else {
row.add_child( row.add_child(
MouseEventHandler::<Cancel, Self>::new(user.id as usize, cx, |mouse_state, _| { MouseEventHandler::new::<Cancel, _>(user.id as usize, cx, |mouse_state, _| {
let button_style = if is_contact_request_pending { let button_style = if is_contact_request_pending {
&theme.disabled_button &theme.disabled_button
} else { } else {
@ -2266,7 +2258,7 @@ impl View for CollabPanel {
return Flex::column() return Flex::column()
.with_child( .with_child(
MouseEventHandler::<LogInButton, _>::new(0, cx, |state, _| { MouseEventHandler::new::<LogInButton, _>(0, cx, |state, _| {
let button = theme.log_in_button.style_for(state); let button = theme.log_in_button.style_for(state);
Label::new("Sign in to collaborate", button.text.clone()) Label::new("Sign in to collaborate", button.text.clone())
.contained() .contained()
@ -2287,7 +2279,7 @@ impl View for CollabPanel {
} }
enum PanelFocus {} enum PanelFocus {}
MouseEventHandler::<PanelFocus, _>::new(0, cx, |_, cx| { MouseEventHandler::new::<PanelFocus, _>(0, cx, |_, cx| {
Stack::new() Stack::new()
.with_child( .with_child(
Flex::column() Flex::column()

View File

@ -164,7 +164,7 @@ impl View for ChannelModal {
cx: &mut ViewContext<ChannelModal>, cx: &mut ViewContext<ChannelModal>,
) -> AnyElement<ChannelModal> { ) -> AnyElement<ChannelModal> {
let active = mode == current_mode; let active = mode == current_mode;
MouseEventHandler::<T, _>::new(0, cx, move |state, _| { MouseEventHandler::new::<T, _>(0, cx, move |state, _| {
let contained_text = theme.tab_button.style_for(active, state); let contained_text = theme.tab_button.style_for(active, state);
Label::new(text, contained_text.text.clone()) Label::new(text, contained_text.text.clone())
.contained() .contained()

View File

@ -219,7 +219,7 @@ impl CollabTitlebarItem {
let mut ret = Flex::row().with_child( let mut ret = Flex::row().with_child(
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<ToggleProjectMenu, Self>::new(0, cx, |mouse_state, cx| { MouseEventHandler::new::<ToggleProjectMenu, _>(0, cx, |mouse_state, cx| {
let style = project_style let style = project_style
.in_state(self.project_popover.is_some()) .in_state(self.project_popover.is_some())
.style_for(mouse_state); .style_for(mouse_state);
@ -259,7 +259,7 @@ impl CollabTitlebarItem {
.with_child( .with_child(
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<ToggleVcsMenu, Self>::new( MouseEventHandler::new::<ToggleVcsMenu, _>(
0, 0,
cx, cx,
|mouse_state, cx| { |mouse_state, cx| {
@ -363,7 +363,7 @@ impl CollabTitlebarItem {
self.branch_popover.as_ref().map(|child| { self.branch_popover.as_ref().map(|child| {
let theme = theme::current(cx).clone(); let theme = theme::current(cx).clone();
let child = ChildView::new(child, cx); let child = ChildView::new(child, cx);
let child = MouseEventHandler::<BranchList, Self>::new(0, cx, |_, _| { let child = MouseEventHandler::new::<BranchList, _>(0, cx, |_, _| {
child child
.flex(1., true) .flex(1., true)
.contained() .contained()
@ -399,7 +399,7 @@ impl CollabTitlebarItem {
self.project_popover.as_ref().map(|child| { self.project_popover.as_ref().map(|child| {
let theme = theme::current(cx).clone(); let theme = theme::current(cx).clone();
let child = ChildView::new(child, cx); let child = ChildView::new(child, cx);
let child = MouseEventHandler::<RecentProjects, Self>::new(0, cx, |_, _| { let child = MouseEventHandler::new::<RecentProjects, _>(0, cx, |_, _| {
child child
.flex(1., true) .flex(1., true)
.contained() .contained()
@ -505,7 +505,7 @@ impl CollabTitlebarItem {
let active = room.read(cx).is_screen_sharing(); let active = room.read(cx).is_screen_sharing();
let titlebar = &theme.titlebar; let titlebar = &theme.titlebar;
MouseEventHandler::<ToggleScreenSharing, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<ToggleScreenSharing, _>(0, cx, |state, _| {
let style = titlebar let style = titlebar
.screen_share_button .screen_share_button
.in_state(active) .in_state(active)
@ -554,7 +554,7 @@ impl CollabTitlebarItem {
} }
let titlebar = &theme.titlebar; let titlebar = &theme.titlebar;
MouseEventHandler::<ToggleMute, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<ToggleMute, _>(0, cx, |state, _| {
let style = titlebar let style = titlebar
.toggle_microphone_button .toggle_microphone_button
.in_state(is_muted) .in_state(is_muted)
@ -607,7 +607,7 @@ impl CollabTitlebarItem {
} }
let titlebar = &theme.titlebar; let titlebar = &theme.titlebar;
MouseEventHandler::<ToggleDeafen, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<ToggleDeafen, _>(0, cx, |state, _| {
let style = titlebar let style = titlebar
.toggle_speakers_button .toggle_speakers_button
.in_state(is_deafened) .in_state(is_deafened)
@ -642,7 +642,7 @@ impl CollabTitlebarItem {
let tooltip = "Leave call"; let tooltip = "Leave call";
let titlebar = &theme.titlebar; let titlebar = &theme.titlebar;
MouseEventHandler::<LeaveCall, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<LeaveCall, _>(0, cx, |state, _| {
let style = titlebar.leave_call_button.style_for(state); let style = titlebar.leave_call_button.style_for(state);
Svg::new(icon) Svg::new(icon)
.with_color(style.color) .with_color(style.color)
@ -696,7 +696,7 @@ impl CollabTitlebarItem {
Some( Some(
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<ShareUnshare, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<ShareUnshare, _>(0, cx, |state, _| {
//TODO: Ensure this button has consistent width for both text variations //TODO: Ensure this button has consistent width for both text variations
let style = titlebar.share_button.inactive_state().style_for(state); let style = titlebar.share_button.inactive_state().style_for(state);
Label::new(label, style.text.clone()) Label::new(label, style.text.clone())
@ -742,7 +742,7 @@ impl CollabTitlebarItem {
let avatar_style = &user_menu_button_style.avatar; let avatar_style = &user_menu_button_style.avatar;
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<ToggleUserMenu, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<ToggleUserMenu, _>(0, cx, |state, _| {
let style = user_menu_button_style let style = user_menu_button_style
.user_menu .user_menu
.inactive_state() .inactive_state()
@ -802,7 +802,7 @@ impl CollabTitlebarItem {
fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> { fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let titlebar = &theme.titlebar; let titlebar = &theme.titlebar;
MouseEventHandler::<SignIn, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<SignIn, _>(0, cx, |state, _| {
let style = titlebar.sign_in_button.inactive_state().style_for(state); let style = titlebar.sign_in_button.inactive_state().style_for(state);
Label::new("Sign In", style.text.clone()) Label::new("Sign In", style.text.clone())
.contained() .contained()
@ -1020,7 +1020,7 @@ impl CollabTitlebarItem {
if let Some(replica_id) = replica_id { if let Some(replica_id) = replica_id {
enum ToggleFollow {} enum ToggleFollow {}
content = MouseEventHandler::<ToggleFollow, Self>::new( content = MouseEventHandler::new::<ToggleFollow, _>(
replica_id.into(), replica_id.into(),
cx, cx,
move |_, _| content, move |_, _| content,
@ -1051,7 +1051,7 @@ impl CollabTitlebarItem {
enum JoinProject {} enum JoinProject {}
let user_id = user.id; let user_id = user.id;
content = MouseEventHandler::<JoinProject, Self>::new( content = MouseEventHandler::new::<JoinProject, _>(
peer_id.as_u64() as usize, peer_id.as_u64() as usize,
cx, cx,
move |_, _| content, move |_, _| content,
@ -1139,7 +1139,7 @@ impl CollabTitlebarItem {
.into_any(), .into_any(),
), ),
client::Status::UpgradeRequired => Some( client::Status::UpgradeRequired => Some(
MouseEventHandler::<ConnectionStatusButton, Self>::new(0, cx, |_, _| { MouseEventHandler::new::<ConnectionStatusButton, _>(0, cx, |_, _| {
Label::new( Label::new(
"Please update Zed to collaborate", "Please update Zed to collaborate",
theme.titlebar.outdated_warning.text.clone(), theme.titlebar.outdated_warning.text.clone(),

View File

@ -173,7 +173,7 @@ impl IncomingCallNotification {
let theme = theme::current(cx); let theme = theme::current(cx);
Flex::column() Flex::column()
.with_child( .with_child(
MouseEventHandler::<Accept, Self>::new(0, cx, |_, _| { MouseEventHandler::new::<Accept, _>(0, cx, |_, _| {
let theme = &theme.incoming_call_notification; let theme = &theme.incoming_call_notification;
Label::new("Accept", theme.accept_button.text.clone()) Label::new("Accept", theme.accept_button.text.clone())
.aligned() .aligned()
@ -187,7 +187,7 @@ impl IncomingCallNotification {
.flex(1., true), .flex(1., true),
) )
.with_child( .with_child(
MouseEventHandler::<Decline, Self>::new(0, cx, |_, _| { MouseEventHandler::new::<Decline, _>(0, cx, |_, _| {
let theme = &theme.incoming_call_notification; let theme = &theme.incoming_call_notification;
Label::new("Decline", theme.decline_button.text.clone()) Label::new("Decline", theme.decline_button.text.clone())
.aligned() .aligned()

View File

@ -52,7 +52,7 @@ where
.flex(1., true), .flex(1., true),
) )
.with_child( .with_child(
MouseEventHandler::<Dismiss, V>::new(user.id as usize, cx, |state, _| { MouseEventHandler::new::<Dismiss, _>(user.id as usize, cx, |state, _| {
let style = theme.dismiss_button.style_for(state); let style = theme.dismiss_button.style_for(state);
Svg::new("icons/x_mark_8.svg") Svg::new("icons/x_mark_8.svg")
.with_color(style.color) .with_color(style.color)
@ -92,7 +92,7 @@ where
Flex::row() Flex::row()
.with_children(buttons.into_iter().enumerate().map( .with_children(buttons.into_iter().enumerate().map(
|(ix, (message, handler))| { |(ix, (message, handler))| {
MouseEventHandler::<Button, V>::new(ix, cx, |state, _| { MouseEventHandler::new::<Button, _>(ix, cx, |state, _| {
let button = theme.button.style_for(state); let button = theme.button.style_for(state);
Label::new(message, button.text.clone()) Label::new(message, button.text.clone())
.contained() .contained()

View File

@ -170,7 +170,7 @@ impl ProjectSharedNotification {
let theme = theme::current(cx); let theme = theme::current(cx);
Flex::column() Flex::column()
.with_child( .with_child(
MouseEventHandler::<Open, Self>::new(0, cx, |_, _| { MouseEventHandler::new::<Open, _>(0, cx, |_, _| {
let theme = &theme.project_shared_notification; let theme = &theme.project_shared_notification;
Label::new("Open", theme.open_button.text.clone()) Label::new("Open", theme.open_button.text.clone())
.aligned() .aligned()
@ -182,7 +182,7 @@ impl ProjectSharedNotification {
.flex(1., true), .flex(1., true),
) )
.with_child( .with_child(
MouseEventHandler::<Dismiss, Self>::new(0, cx, |_, _| { MouseEventHandler::new::<Dismiss, _>(0, cx, |_, _| {
let theme = &theme.project_shared_notification; let theme = &theme.project_shared_notification;
Label::new("Dismiss", theme.dismiss_button.text.clone()) Label::new("Dismiss", theme.dismiss_button.text.clone())
.aligned() .aligned()

View File

@ -47,7 +47,7 @@ impl View for SharingStatusIndicator {
Appearance::Dark | Appearance::VibrantDark => Color::white(), Appearance::Dark | Appearance::VibrantDark => Color::white(),
}; };
MouseEventHandler::<Self, Self>::new(0, cx, |_, _| { MouseEventHandler::new::<Self, _>(0, cx, |_, _| {
Svg::new("icons/disable_screen_sharing_12.svg") Svg::new("icons/disable_screen_sharing_12.svg")
.with_color(color) .with_color(color)
.constrained() .constrained()

View File

@ -439,14 +439,14 @@ impl ContextMenu {
let style = theme::current(cx).context_menu.clone(); let style = theme::current(cx).context_menu.clone();
MouseEventHandler::<Menu, ContextMenu>::new(0, cx, |_, cx| { MouseEventHandler::new::<Menu, _>(0, cx, |_, cx| {
Flex::column() Flex::column()
.with_children(self.items.iter().enumerate().map(|(ix, item)| { .with_children(self.items.iter().enumerate().map(|(ix, item)| {
match item { match item {
ContextMenuItem::Item { label, action } => { ContextMenuItem::Item { label, action } => {
let action = action.clone(); let action = action.clone();
let view_id = self.parent_view_id; let view_id = self.parent_view_id;
MouseEventHandler::<MenuItem, ContextMenu>::new(ix, cx, |state, _| { MouseEventHandler::new::<MenuItem, _>(ix, cx, |state, _| {
let style = style.item.in_state(self.selected_index == Some(ix)); let style = style.item.in_state(self.selected_index == Some(ix));
let style = style.style_for(state); let style = style.style_for(state);
let keystroke = match &action { let keystroke = match &action {

View File

@ -113,7 +113,7 @@ impl CopilotCodeVerification {
let device_code_style = &style.auth.prompting.device_code; let device_code_style = &style.auth.prompting.device_code;
MouseEventHandler::<Self, _>::new(0, cx, |state, _cx| { MouseEventHandler::new::<Self, _>(0, cx, |state, _cx| {
Flex::row() Flex::row()
.with_child( .with_child(
Label::new(data.user_code.clone(), device_code_style.text.clone()) Label::new(data.user_code.clone(), device_code_style.text.clone())

View File

@ -62,7 +62,7 @@ impl View for CopilotButton {
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<Self, _>::new(0, cx, { MouseEventHandler::new::<Self, _>(0, cx, {
let theme = theme.clone(); let theme = theme.clone();
let status = status.clone(); let status = status.clone();
move |state, _cx| { move |state, _cx| {

View File

@ -94,7 +94,7 @@ impl View for DiagnosticIndicator {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
let in_progress = !self.in_progress_checks.is_empty(); let in_progress = !self.in_progress_checks.is_empty();
let mut element = Flex::row().with_child( let mut element = Flex::row().with_child(
MouseEventHandler::<Summary, _>::new(0, cx, |state, cx| { MouseEventHandler::new::<Summary, _>(0, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme let style = theme
.workspace .workspace
@ -195,7 +195,7 @@ impl View for DiagnosticIndicator {
} else if let Some(diagnostic) = &self.current_diagnostic { } else if let Some(diagnostic) = &self.current_diagnostic {
let message_style = style.diagnostic_message.clone(); let message_style = style.diagnostic_message.clone();
element.add_child( element.add_child(
MouseEventHandler::<Message, _>::new(1, cx, |state, _| { MouseEventHandler::new::<Message, _>(1, cx, |state, _| {
Label::new( Label::new(
diagnostic.message.split('\n').next().unwrap().to_string(), diagnostic.message.split('\n').next().unwrap().to_string(),
message_style.style_for(state).text.clone(), message_style.style_for(state).text.clone(),

View File

@ -202,7 +202,7 @@ impl<V: View> DragAndDrop<V> {
let position = (position - region_offset).round(); let position = (position - region_offset).round();
Some( Some(
Overlay::new( Overlay::new(
MouseEventHandler::<DraggedElementHandler, V>::new( MouseEventHandler::new::<DraggedElementHandler, _>(
0, 0,
cx, cx,
|_, cx| render(payload, cx), |_, cx| render(payload, cx),
@ -235,7 +235,7 @@ impl<V: View> DragAndDrop<V> {
} }
State::Canceled => Some( State::Canceled => Some(
MouseEventHandler::<DraggedElementHandler, V>::new(0, cx, |_, _| { MouseEventHandler::new::<DraggedElementHandler, _>(0, cx, |_, _| {
Empty::new().constrained().with_width(0.).with_height(0.) Empty::new().constrained().with_width(0.).with_height(0.)
}) })
.on_up(MouseButton::Left, |_, _, cx| { .on_up(MouseButton::Left, |_, _, cx| {
@ -301,7 +301,7 @@ pub trait Draggable<V: View> {
Self: Sized; Self: Sized;
} }
impl<Tag, V: View> Draggable<V> for MouseEventHandler<Tag, V> { impl<V: View> Draggable<V> for MouseEventHandler<V> {
fn as_draggable<D: View, P: Any>( fn as_draggable<D: View, P: Any>(
self, self,
payload: P, payload: P,

View File

@ -867,7 +867,7 @@ impl CompletionsMenu {
let completion = &completions[mat.candidate_id]; let completion = &completions[mat.candidate_id];
let item_ix = start_ix + ix; let item_ix = start_ix + ix;
items.push( items.push(
MouseEventHandler::<CompletionTag, _>::new( MouseEventHandler::new::<CompletionTag, _>(
mat.candidate_id, mat.candidate_id,
cx, cx,
|state, _| { |state, _| {
@ -1044,7 +1044,7 @@ impl CodeActionsMenu {
for (ix, action) in actions[range].iter().enumerate() { for (ix, action) in actions[range].iter().enumerate() {
let item_ix = start_ix + ix; let item_ix = start_ix + ix;
items.push( items.push(
MouseEventHandler::<ActionTag, _>::new(item_ix, cx, |state, _| { MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
let item_style = if item_ix == selected_item { let item_style = if item_ix == selected_item {
style.autocomplete.selected_item style.autocomplete.selected_item
} else if state.hovered() { } else if state.hovered() {
@ -2723,7 +2723,7 @@ impl Editor {
.collect() .collect()
} }
fn excerpt_visible_offsets( pub fn excerpt_visible_offsets(
&self, &self,
restrict_to_languages: Option<&HashSet<Arc<Language>>>, restrict_to_languages: Option<&HashSet<Arc<Language>>>,
cx: &mut ViewContext<'_, '_, Editor>, cx: &mut ViewContext<'_, '_, Editor>,
@ -3547,7 +3547,7 @@ impl Editor {
if self.available_code_actions.is_some() { if self.available_code_actions.is_some() {
enum CodeActions {} enum CodeActions {}
Some( Some(
MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| { MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
Svg::new("icons/bolt_8.svg").with_color( Svg::new("icons/bolt_8.svg").with_color(
style style
.code_actions .code_actions
@ -3594,7 +3594,7 @@ impl Editor {
fold_data fold_data
.map(|(fold_status, buffer_row, active)| { .map(|(fold_status, buffer_row, active)| {
(active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| { (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
MouseEventHandler::<FoldIndicators, _>::new( MouseEventHandler::new::<FoldIndicators, _>(
ix as usize, ix as usize,
cx, cx,
|mouse_state, _| { |mouse_state, _| {
@ -8663,7 +8663,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend
let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round(); let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
let anchor_x = cx.anchor_x; let anchor_x = cx.anchor_x;
enum BlockContextToolip {} enum BlockContextToolip {}
MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| { MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
Flex::column() Flex::column()
.with_children(highlighted_lines.iter().map(|(line, highlights)| { .with_children(highlighted_lines.iter().map(|(line, highlights)| {
Label::new( Label::new(

View File

@ -1637,7 +1637,7 @@ impl EditorElement {
let jump_position = language::ToPoint::to_point(&jump_anchor, buffer); let jump_position = language::ToPoint::to_point(&jump_anchor, buffer);
enum JumpIcon {} enum JumpIcon {}
MouseEventHandler::<JumpIcon, _>::new((*id).into(), cx, |state, _| { MouseEventHandler::new::<JumpIcon, _>((*id).into(), cx, |state, _| {
let style = style.jump_icon.style_for(state); let style = style.jump_icon.style_for(state);
Svg::new("icons/arrow_up_right_8.svg") Svg::new("icons/arrow_up_right_8.svg")
.with_color(style.color) .with_color(style.color)

View File

@ -565,7 +565,7 @@ impl InfoPopover {
) )
}); });
MouseEventHandler::<InfoPopover, _>::new(0, cx, |_, cx| { MouseEventHandler::new::<InfoPopover, _>(0, cx, |_, cx| {
let mut region_id = 0; let mut region_id = 0;
let view_id = cx.view_id(); let view_id = cx.view_id();
@ -654,7 +654,7 @@ impl DiagnosticPopover {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
MouseEventHandler::<DiagnosticPopover, _>::new(0, cx, |_, _| { MouseEventHandler::new::<DiagnosticPopover, _>(0, cx, |_, _| {
text.with_soft_wrap(true) text.with_soft_wrap(true)
.contained() .contained()
.with_style(container_style) .with_style(container_style)

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ use gpui::{
}; };
use language::{Bias, Point}; use language::{Bias, Point};
use util::ResultExt; use util::ResultExt;
use workspace::{item::Item, WorkspaceId}; use workspace::WorkspaceId;
use crate::{ use crate::{
display_map::{DisplaySnapshot, ToDisplayPoint}, display_map::{DisplaySnapshot, ToDisplayPoint},
@ -333,9 +333,7 @@ impl Editor {
cx, cx,
); );
if !self.is_singleton(cx) { self.refresh_inlays(InlayRefreshReason::NewLinesShown, cx);
self.refresh_inlays(InlayRefreshReason::NewLinesShown, cx);
}
} }
pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F { pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {

View File

@ -35,7 +35,7 @@ impl View for DeployFeedbackButton {
let theme = theme::current(cx).clone(); let theme = theme::current(cx).clone();
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<Self, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<Self, _>(0, cx, |state, _| {
let style = &theme let style = &theme
.workspace .workspace
.status_bar .status_bar

View File

@ -41,7 +41,7 @@ impl View for FeedbackInfoText {
.aligned(), .aligned(),
) )
.with_child( .with_child(
MouseEventHandler::<OpenZedCommunityRepo, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<OpenZedCommunityRepo, _>(0, cx, |state, _| {
let contained_text = if state.hovered() { let contained_text = if state.hovered() {
&theme.feedback.link_text_hover &theme.feedback.link_text_hover
} else { } else {

View File

@ -52,7 +52,7 @@ impl View for SubmitFeedbackButton {
.map_or(true, |i| i.read(cx).allow_submission); .map_or(true, |i| i.read(cx).allow_submission);
enum SubmitFeedbackButton {} enum SubmitFeedbackButton {}
MouseEventHandler::<SubmitFeedbackButton, Self>::new(0, cx, |state, _| { MouseEventHandler::new::<SubmitFeedbackButton, _>(0, cx, |state, _| {
let text; let text;
let style = if allow_submission { let style = if allow_submission {
text = "Submit as Markdown"; text = "Submit as Markdown";

View File

@ -0,0 +1,335 @@
use button_component::Button;
use component::AdaptComponent;
use gpui::{
color::Color,
elements::{ContainerStyle, Flex, Label, ParentElement},
fonts::{self, TextStyle},
platform::WindowOptions,
AnyElement, App, Element, Entity, View, ViewContext,
};
use log::LevelFilter;
use pathfinder_geometry::vector::vec2f;
use simplelog::SimpleLogger;
use theme::Toggleable;
use toggleable_button::ToggleableButton;
fn main() {
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
App::new(()).unwrap().run(|cx| {
cx.platform().activate(true);
cx.add_window(WindowOptions::with_bounds(vec2f(300., 200.)), |_| {
TestView {
count: 0,
is_doubling: false,
}
});
});
}
pub struct TestView {
count: usize,
is_doubling: bool,
}
impl TestView {
fn increase_count(&mut self) {
if self.is_doubling {
self.count *= 2;
} else {
self.count += 1;
}
}
}
impl Entity for TestView {
type Event = ();
}
type ButtonStyle = ContainerStyle;
impl View for TestView {
fn ui_name() -> &'static str {
"TestView"
}
fn render(&mut self, cx: &mut ViewContext<'_, '_, Self>) -> AnyElement<Self> {
fonts::with_font_cache(cx.font_cache.to_owned(), || {
Flex::column()
.with_child(Label::new(
format!("Count: {}", self.count),
TextStyle::for_color(Color::red()),
))
.with_child(
Button::new(move |_, v: &mut Self, cx| {
v.increase_count();
cx.notify();
})
.with_text(
"Hello from a counting BUTTON",
TextStyle::for_color(Color::blue()),
)
.with_style(ButtonStyle::fill(Color::yellow()))
.into_element(),
)
.with_child(
ToggleableButton::new(self.is_doubling, move |_, v: &mut Self, cx| {
v.is_doubling = !v.is_doubling;
cx.notify();
})
.with_text("Double the count?", TextStyle::for_color(Color::black()))
.with_style(Toggleable {
inactive: ButtonStyle::fill(Color::red()),
active: ButtonStyle::fill(Color::green()),
})
.into_element(),
)
.expanded()
.contained()
.with_background_color(Color::white())
.into_any()
})
}
}
mod theme {
pub struct Toggleable<T> {
pub inactive: T,
pub active: T,
}
impl<T> Toggleable<T> {
pub fn style_for(&self, active: bool) -> &T {
if active {
&self.active
} else {
&self.inactive
}
}
}
}
// Component creation:
mod toggleable_button {
use gpui::{
elements::{ContainerStyle, LabelStyle},
scene::MouseClick,
EventContext, View,
};
use crate::{button_component::Button, component::Component, theme::Toggleable};
pub struct ToggleableButton<V: View> {
active: bool,
style: Option<Toggleable<ContainerStyle>>,
button: Button<V>,
}
impl<V: View> ToggleableButton<V> {
pub fn new<F>(active: bool, on_click: F) -> Self
where
F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
{
Self {
active,
button: Button::new(on_click),
style: None,
}
}
pub fn with_text(self, text: &str, style: impl Into<LabelStyle>) -> ToggleableButton<V> {
ToggleableButton {
active: self.active,
style: self.style,
button: self.button.with_text(text, style),
}
}
pub fn with_style(self, style: Toggleable<ContainerStyle>) -> ToggleableButton<V> {
ToggleableButton {
active: self.active,
style: Some(style),
button: self.button,
}
}
}
impl<V: View> Component for ToggleableButton<V> {
type View = V;
fn render(
self,
v: &mut Self::View,
cx: &mut gpui::ViewContext<Self::View>,
) -> gpui::AnyElement<V> {
let button = if let Some(style) = self.style {
self.button.with_style(*style.style_for(self.active))
} else {
self.button
};
button.render(v, cx)
}
}
}
mod button_component {
use gpui::{
elements::{ContainerStyle, Label, LabelStyle, MouseEventHandler},
platform::MouseButton,
scene::MouseClick,
AnyElement, Element, EventContext, TypeTag, View, ViewContext,
};
use crate::component::Component;
type ClickHandler<V> = Box<dyn Fn(MouseClick, &mut V, &mut EventContext<V>)>;
pub struct Button<V: View> {
click_handler: ClickHandler<V>,
tag: TypeTag,
contents: Option<AnyElement<V>>,
style: Option<ContainerStyle>,
}
impl<V: View> Button<V> {
pub fn new<F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static>(handler: F) -> Self {
Self {
click_handler: Box::new(handler),
tag: TypeTag::new::<F>(),
style: None,
contents: None,
}
}
pub fn with_text(mut self, text: &str, style: impl Into<LabelStyle>) -> Self {
self.contents = Some(Label::new(text.to_string(), style).into_any());
self
}
pub fn _with_contents<E: Element<V>>(mut self, contents: E) -> Self {
self.contents = Some(contents.into_any());
self
}
pub fn with_style(mut self, style: ContainerStyle) -> Self {
self.style = Some(style);
self
}
}
impl<V: View> Component for Button<V> {
type View = V;
fn render(self, _: &mut Self::View, cx: &mut ViewContext<V>) -> AnyElement<Self::View> {
let click_handler = self.click_handler;
let result = MouseEventHandler::new_dynamic(self.tag, 0, cx, |_, _| {
self.contents
.unwrap_or_else(|| gpui::elements::Empty::new().into_any())
})
.on_click(MouseButton::Left, move |click, v, cx| {
click_handler(click, v, cx);
})
.contained();
let result = if let Some(style) = self.style {
result.with_style(style)
} else {
result
};
result.into_any()
}
}
}
mod component {
use gpui::{AnyElement, Element, View, ViewContext};
use pathfinder_geometry::vector::Vector2F;
// Public API:
pub trait Component {
type View: View;
fn render(
self,
v: &mut Self::View,
cx: &mut ViewContext<Self::View>,
) -> AnyElement<Self::View>;
}
pub struct ComponentAdapter<E> {
component: Option<E>,
}
impl<E> ComponentAdapter<E> {
pub fn new(e: E) -> Self {
Self { component: Some(e) }
}
}
pub trait AdaptComponent<C: Component>: Sized {
fn into_element(self) -> ComponentAdapter<Self> {
ComponentAdapter::new(self)
}
}
impl<C: Component> AdaptComponent<C> for C {}
impl<C: Component + 'static> Element<C::View> for ComponentAdapter<C> {
type LayoutState = AnyElement<C::View>;
type PaintState = ();
fn layout(
&mut self,
constraint: gpui::SizeConstraint,
view: &mut C::View,
cx: &mut gpui::LayoutContext<C::View>,
) -> (Vector2F, Self::LayoutState) {
let component = self.component.take().unwrap();
let mut element = component.render(view, cx.view_context());
let constraint = element.layout(constraint, view, cx);
(constraint, element)
}
fn paint(
&mut self,
scene: &mut gpui::SceneBuilder,
bounds: gpui::geometry::rect::RectF,
visible_bounds: gpui::geometry::rect::RectF,
layout: &mut Self::LayoutState,
view: &mut C::View,
cx: &mut gpui::PaintContext<C::View>,
) -> Self::PaintState {
layout.paint(scene, bounds.origin(), visible_bounds, view, cx)
}
fn rect_for_text_range(
&self,
_: std::ops::Range<usize>,
_: gpui::geometry::rect::RectF,
_: gpui::geometry::rect::RectF,
_: &Self::LayoutState,
_: &Self::PaintState,
_: &C::View,
_: &ViewContext<C::View>,
) -> Option<gpui::geometry::rect::RectF> {
todo!()
}
fn debug(
&self,
_: gpui::geometry::rect::RectF,
_: &Self::LayoutState,
_: &Self::PaintState,
_: &C::View,
_: &ViewContext<C::View>,
) -> serde_json::Value {
todo!()
}
}
}

View File

@ -3280,7 +3280,11 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
} }
pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState { pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id); self.mouse_state_dynamic(TypeTag::new::<Tag>(), region_id)
}
pub fn mouse_state_dynamic(&self, tag: TypeTag, region_id: usize) -> MouseState {
let region_id = MouseRegionId::new(tag, self.view_id, region_id);
MouseState { MouseState {
hovered: self.window.hovered_region_ids.contains(&region_id), hovered: self.window.hovered_region_ids.contains(&region_id),
clicked: if let Some((clicked_region_id, button)) = self.window.clicked_region { clicked: if let Some((clicked_region_id, button)) = self.window.clicked_region {
@ -3321,6 +3325,36 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
} }
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct TypeTag {
tag: TypeId,
#[cfg(debug_assertions)]
tag_type_name: &'static str,
}
impl TypeTag {
pub fn new<Tag: 'static>() -> Self {
Self {
tag: TypeId::of::<Tag>(),
#[cfg(debug_assertions)]
tag_type_name: std::any::type_name::<Tag>(),
}
}
pub fn dynamic(tag: TypeId, #[cfg(debug_assertions)] type_name: &'static str) -> Self {
Self {
tag,
#[cfg(debug_assertions)]
tag_type_name: type_name,
}
}
#[cfg(debug_assertions)]
pub(crate) fn type_name(&self) -> &'static str {
self.tag_type_name
}
}
impl<V> BorrowAppContext for ViewContext<'_, '_, V> { impl<V> BorrowAppContext for ViewContext<'_, '_, V> {
fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T { fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
BorrowAppContext::read_with(&*self.window_context, f) BorrowAppContext::read_with(&*self.window_context, f)
@ -5171,7 +5205,7 @@ mod tests {
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> { fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
enum Handler {} enum Handler {}
let mouse_down_count = self.mouse_down_count.clone(); let mouse_down_count = self.mouse_down_count.clone();
MouseEventHandler::<Handler, _>::new(0, cx, |_, _| Empty::new()) MouseEventHandler::new::<Handler, _>(0, cx, |_, _| Empty::new())
.on_down(MouseButton::Left, move |_, _, _| { .on_down(MouseButton::Left, move |_, _, _| {
mouse_down_count.fetch_add(1, SeqCst); mouse_down_count.fetch_add(1, SeqCst);
}) })

View File

@ -197,11 +197,11 @@ pub trait Element<V: View>: 'static {
Resizable::new(self.into_any(), side, size, on_resize) Resizable::new(self.into_any(), side, size, on_resize)
} }
fn mouse<Tag>(self, region_id: usize) -> MouseEventHandler<Tag, V> fn mouse<Tag: 'static>(self, region_id: usize) -> MouseEventHandler<V>
where where
Self: Sized, Self: Sized,
{ {
MouseEventHandler::for_child(self.into_any(), region_id) MouseEventHandler::for_child::<Tag>(self.into_any(), region_id)
} }
} }

View File

@ -38,6 +38,15 @@ pub struct ContainerStyle {
pub cursor: Option<CursorStyle>, pub cursor: Option<CursorStyle>,
} }
impl ContainerStyle {
pub fn fill(color: Color) -> Self {
Self {
background_color: Some(color),
..Default::default()
}
}
}
pub struct Container<V: View> { pub struct Container<V: View> {
child: AnyElement<V>, child: AnyElement<V>,
style: ContainerStyle, style: ContainerStyle,

View File

@ -11,12 +11,12 @@ use crate::{
MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
}, },
AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, PaintContext, AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, PaintContext,
SceneBuilder, SizeConstraint, View, ViewContext, SceneBuilder, SizeConstraint, TypeTag, View, ViewContext,
}; };
use serde_json::json; use serde_json::json;
use std::{marker::PhantomData, ops::Range}; use std::ops::Range;
pub struct MouseEventHandler<Tag: 'static, V: View> { pub struct MouseEventHandler<V: View> {
child: AnyElement<V>, child: AnyElement<V>,
region_id: usize, region_id: usize,
cursor_style: Option<CursorStyle>, cursor_style: Option<CursorStyle>,
@ -26,13 +26,13 @@ pub struct MouseEventHandler<Tag: 'static, V: View> {
notify_on_click: bool, notify_on_click: bool,
above: bool, above: bool,
padding: Padding, padding: Padding,
_tag: PhantomData<Tag>, tag: TypeTag,
} }
/// Element which provides a render_child callback with a MouseState and paints a mouse /// Element which provides a render_child callback with a MouseState and paints a mouse
/// region under (or above) it for easy mouse event handling. /// region under (or above) it for easy mouse event handling.
impl<Tag, V: View> MouseEventHandler<Tag, V> { impl<V: View> MouseEventHandler<V> {
pub fn for_child(child: impl Element<V>, region_id: usize) -> Self { pub fn for_child<Tag: 'static>(child: impl Element<V>, region_id: usize) -> Self {
Self { Self {
child: child.into_any(), child: child.into_any(),
region_id, region_id,
@ -43,16 +43,19 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
hoverable: false, hoverable: false,
above: false, above: false,
padding: Default::default(), padding: Default::default(),
_tag: PhantomData, tag: TypeTag::new::<Tag>(),
} }
} }
pub fn new<E, F>(region_id: usize, cx: &mut ViewContext<V>, render_child: F) -> Self pub fn new<Tag: 'static, E>(
region_id: usize,
cx: &mut ViewContext<V>,
render_child: impl FnOnce(&mut MouseState, &mut ViewContext<V>) -> E,
) -> Self
where where
E: Element<V>, E: Element<V>,
F: FnOnce(&mut MouseState, &mut ViewContext<V>) -> E,
{ {
let mut mouse_state = cx.mouse_state::<Tag>(region_id); let mut mouse_state = cx.mouse_state_dynamic(TypeTag::new::<Tag>(), region_id);
let child = render_child(&mut mouse_state, cx).into_any(); let child = render_child(&mut mouse_state, cx).into_any();
let notify_on_hover = mouse_state.accessed_hovered(); let notify_on_hover = mouse_state.accessed_hovered();
let notify_on_click = mouse_state.accessed_clicked(); let notify_on_click = mouse_state.accessed_clicked();
@ -66,19 +69,46 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
hoverable: true, hoverable: true,
above: false, above: false,
padding: Default::default(), padding: Default::default(),
_tag: PhantomData, tag: TypeTag::new::<Tag>(),
}
}
pub fn new_dynamic(
tag: TypeTag,
region_id: usize,
cx: &mut ViewContext<V>,
render_child: impl FnOnce(&mut MouseState, &mut ViewContext<V>) -> AnyElement<V>,
) -> Self {
let mut mouse_state = cx.mouse_state_dynamic(tag, region_id);
let child = render_child(&mut mouse_state, cx);
let notify_on_hover = mouse_state.accessed_hovered();
let notify_on_click = mouse_state.accessed_clicked();
Self {
child,
region_id,
cursor_style: None,
handlers: Default::default(),
notify_on_hover,
notify_on_click,
hoverable: true,
above: false,
padding: Default::default(),
tag,
} }
} }
/// Modifies the MouseEventHandler to render the MouseRegion above the child element. Useful /// Modifies the MouseEventHandler to render the MouseRegion above the child element. Useful
/// for drag and drop handling and similar events which should be captured before the child /// for drag and drop handling and similar events which should be captured before the child
/// gets the opportunity /// gets the opportunity
pub fn above<D, F>(region_id: usize, cx: &mut ViewContext<V>, render_child: F) -> Self pub fn above<Tag: 'static, D>(
region_id: usize,
cx: &mut ViewContext<V>,
render_child: impl FnOnce(&mut MouseState, &mut ViewContext<V>) -> D,
) -> Self
where where
D: Element<V>, D: Element<V>,
F: FnOnce(&mut MouseState, &mut ViewContext<V>) -> D,
{ {
let mut handler = Self::new(region_id, cx, render_child); let mut handler = Self::new::<Tag, _>(region_id, cx, render_child);
handler.above = true; handler.above = true;
handler handler
} }
@ -223,7 +253,8 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
}); });
} }
scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::from_handlers::<Tag>( MouseRegion::from_handlers(
self.tag,
cx.view_id(), cx.view_id(),
self.region_id, self.region_id,
hit_bounds, hit_bounds,
@ -236,7 +267,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
} }
} }
impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> { impl<V: View> Element<V> for MouseEventHandler<V> {
type LayoutState = (); type LayoutState = ();
type PaintState = (); type PaintState = ();

View File

@ -95,7 +95,7 @@ impl<V: View> Tooltip<V> {
} else { } else {
None None
}; };
let child = MouseEventHandler::<MouseEventHandlerState<Tag>, _>::new(id, cx, |_, _| child) let child = MouseEventHandler::new::<MouseEventHandlerState<Tag>, _>(id, cx, |_, _| child)
.on_hover(move |e, _, cx| { .on_hover(move |e, _, cx| {
let position = e.position; let position = e.position;
if e.started { if e.started {

View File

@ -72,6 +72,13 @@ pub struct TextStyle {
} }
impl TextStyle { impl TextStyle {
pub fn for_color(color: Color) -> Self {
Self {
color,
..Default::default()
}
}
pub fn refine(self, refinement: TextStyleRefinement) -> TextStyle { pub fn refine(self, refinement: TextStyleRefinement) -> TextStyle {
TextStyle { TextStyle {
color: refinement.color.unwrap_or(self.color), color: refinement.color.unwrap_or(self.color),

View File

@ -24,6 +24,7 @@ use crate::{
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use async_task::Runnable; use async_task::Runnable;
pub use event::*; pub use event::*;
use pathfinder_geometry::vector::vec2f;
use postage::oneshot; use postage::oneshot;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::Deserialize; use serde::Deserialize;
@ -180,6 +181,16 @@ pub struct WindowOptions<'a> {
pub screen: Option<Rc<dyn Screen>>, pub screen: Option<Rc<dyn Screen>>,
} }
impl<'a> WindowOptions<'a> {
pub fn with_bounds(bounds: Vector2F) -> Self {
Self {
bounds: WindowBounds::Fixed(RectF::new(vec2f(0., 0.), bounds)),
center: true,
..Default::default()
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct TitlebarOptions<'a> { pub struct TitlebarOptions<'a> {
pub title: Option<&'a str>, pub title: Option<&'a str>,

View File

@ -1,13 +1,10 @@
use crate::{platform::MouseButton, window::WindowContext, EventContext, View, ViewContext}; use crate::{
platform::MouseButton, window::WindowContext, EventContext, TypeTag, View, ViewContext,
};
use collections::HashMap; use collections::HashMap;
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{ use std::{any::Any, fmt::Debug, mem::Discriminant, rc::Rc};
any::{Any, TypeId},
fmt::Debug,
mem::Discriminant,
rc::Rc,
};
use super::{ use super::{
mouse_event::{ mouse_event::{
@ -33,14 +30,27 @@ impl MouseRegion {
/// should pass a different (consistent) region_id. If you have one big region that covers your /// should pass a different (consistent) region_id. If you have one big region that covers your
/// whole component, just pass the view_id again. /// whole component, just pass the view_id again.
pub fn new<Tag: 'static>(view_id: usize, region_id: usize, bounds: RectF) -> Self { pub fn new<Tag: 'static>(view_id: usize, region_id: usize, bounds: RectF) -> Self {
Self::from_handlers::<Tag>(view_id, region_id, bounds, Default::default()) Self::from_handlers(
TypeTag::new::<Tag>(),
view_id,
region_id,
bounds,
Default::default(),
)
} }
pub fn handle_all<Tag: 'static>(view_id: usize, region_id: usize, bounds: RectF) -> Self { pub fn handle_all<Tag: 'static>(view_id: usize, region_id: usize, bounds: RectF) -> Self {
Self::from_handlers::<Tag>(view_id, region_id, bounds, HandlerSet::capture_all()) Self::from_handlers(
TypeTag::new::<Tag>(),
view_id,
region_id,
bounds,
HandlerSet::capture_all(),
)
} }
pub fn from_handlers<Tag: 'static>( pub fn from_handlers(
tag: TypeTag,
view_id: usize, view_id: usize,
region_id: usize, region_id: usize,
bounds: RectF, bounds: RectF,
@ -49,10 +59,8 @@ impl MouseRegion {
Self { Self {
id: MouseRegionId { id: MouseRegionId {
view_id, view_id,
tag: TypeId::of::<Tag>(), tag,
region_id, region_id,
#[cfg(debug_assertions)]
tag_type_name: std::any::type_name::<Tag>(),
}, },
bounds, bounds,
handlers, handlers,
@ -180,20 +188,16 @@ impl MouseRegion {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)]
pub struct MouseRegionId { pub struct MouseRegionId {
view_id: usize, view_id: usize,
tag: TypeId, tag: TypeTag,
region_id: usize, region_id: usize,
#[cfg(debug_assertions)]
tag_type_name: &'static str,
} }
impl MouseRegionId { impl MouseRegionId {
pub(crate) fn new<Tag: 'static>(view_id: usize, region_id: usize) -> Self { pub(crate) fn new(tag: TypeTag, view_id: usize, region_id: usize) -> Self {
MouseRegionId { MouseRegionId {
view_id, view_id,
region_id, region_id,
tag: TypeId::of::<Tag>(), tag,
#[cfg(debug_assertions)]
tag_type_name: std::any::type_name::<Tag>(),
} }
} }
@ -203,7 +207,7 @@ impl MouseRegionId {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
pub fn tag_type_name(&self) -> &'static str { pub fn tag_type_name(&self) -> &'static str {
self.tag_type_name self.tag.type_name()
} }
} }

View File

@ -106,7 +106,7 @@ impl View for Select {
Default::default() Default::default()
}; };
let mut result = Flex::column().with_child( let mut result = Flex::column().with_child(
MouseEventHandler::<Header, _>::new(self.handle.id(), cx, |mouse_state, cx| { MouseEventHandler::new::<Header, _>(self.handle.id(), cx, |mouse_state, cx| {
(self.render_item)( (self.render_item)(
self.selected_item_ix, self.selected_item_ix,
ItemType::Header, ItemType::Header,
@ -130,7 +130,7 @@ impl View for Select {
let selected_item_ix = this.selected_item_ix; let selected_item_ix = this.selected_item_ix;
range.end = range.end.min(this.item_count); range.end = range.end.min(this.item_count);
items.extend(range.map(|ix| { items.extend(range.map(|ix| {
MouseEventHandler::<Item, _>::new(ix, cx, |mouse_state, cx| { MouseEventHandler::new::<Item, _>(ix, cx, |mouse_state, cx| {
(this.render_item)( (this.render_item)(
ix, ix,
if ix == selected_item_ix { if ix == selected_item_ix {

View File

@ -53,7 +53,7 @@ impl View for ActiveBufferLanguage {
"Unknown".to_string() "Unknown".to_string()
}; };
MouseEventHandler::<Self, Self>::new(0, cx, |state, cx| { MouseEventHandler::new::<Self, _>(0, cx, |state, cx| {
let theme = &theme::current(cx).workspace.status_bar; let theme = &theme::current(cx).workspace.status_bar;
let style = theme.active_language.style_for(state); let style = theme.active_language.style_for(state);
Label::new(active_language_text, style.text.clone()) Label::new(active_language_text, style.text.clone())

View File

@ -573,7 +573,7 @@ impl View for LspLogToolbarItemView {
.with_children(if self.menu_open { .with_children(if self.menu_open {
Some( Some(
Overlay::new( Overlay::new(
MouseEventHandler::<Menu, _>::new(0, cx, move |_, cx| { MouseEventHandler::new::<Menu, _>(0, cx, move |_, cx| {
Flex::column() Flex::column()
.with_children(menu_rows.into_iter().map(|row| { .with_children(menu_rows.into_iter().map(|row| {
Self::render_language_server_menu_item( Self::render_language_server_menu_item(
@ -672,7 +672,7 @@ impl LspLogToolbarItemView {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> impl Element<Self> { ) -> impl Element<Self> {
enum ToggleMenu {} enum ToggleMenu {}
MouseEventHandler::<ToggleMenu, Self>::new(0, cx, move |state, cx| { MouseEventHandler::new::<ToggleMenu, _>(0, cx, move |state, cx| {
let label: Cow<str> = current_server let label: Cow<str> = current_server
.and_then(|row| { .and_then(|row| {
let worktree = row.worktree.read(cx); let worktree = row.worktree.read(cx);
@ -728,7 +728,7 @@ impl LspLogToolbarItemView {
.with_height(theme.toolbar_dropdown_menu.row_height) .with_height(theme.toolbar_dropdown_menu.row_height)
}) })
.with_child( .with_child(
MouseEventHandler::<ActivateLog, _>::new(id.0, cx, move |state, _| { MouseEventHandler::new::<ActivateLog, _>(id.0, cx, move |state, _| {
let style = theme let style = theme
.toolbar_dropdown_menu .toolbar_dropdown_menu
.item .item
@ -746,7 +746,7 @@ impl LspLogToolbarItemView {
}), }),
) )
.with_child( .with_child(
MouseEventHandler::<ActivateRpcTrace, _>::new(id.0, cx, move |state, cx| { MouseEventHandler::new::<ActivateRpcTrace, _>(id.0, cx, move |state, cx| {
let style = theme let style = theme
.toolbar_dropdown_menu .toolbar_dropdown_menu
.item .item

View File

@ -389,7 +389,7 @@ impl View for SyntaxTreeView {
{ {
let layer = layer.clone(); let layer = layer.clone();
let theme = editor_theme.clone(); let theme = editor_theme.clone();
return MouseEventHandler::<Self, Self>::new(0, cx, move |state, cx| { return MouseEventHandler::new::<Self, _>(0, cx, move |state, cx| {
let list_hovered = state.hovered(); let list_hovered = state.hovered();
UniformList::new( UniformList::new(
self.list_state.clone(), self.list_state.clone(),
@ -505,7 +505,7 @@ impl SyntaxTreeToolbarItemView {
.with_child(Self::render_header(&theme, &active_layer, cx)) .with_child(Self::render_header(&theme, &active_layer, cx))
.with_children(self.menu_open.then(|| { .with_children(self.menu_open.then(|| {
Overlay::new( Overlay::new(
MouseEventHandler::<Menu, _>::new(0, cx, move |_, cx| { MouseEventHandler::new::<Menu, _>(0, cx, move |_, cx| {
Flex::column() Flex::column()
.with_children(active_buffer.syntax_layers().enumerate().map( .with_children(active_buffer.syntax_layers().enumerate().map(
|(ix, layer)| { |(ix, layer)| {
@ -564,7 +564,7 @@ impl SyntaxTreeToolbarItemView {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> impl Element<Self> { ) -> impl Element<Self> {
enum ToggleMenu {} enum ToggleMenu {}
MouseEventHandler::<ToggleMenu, Self>::new(0, cx, move |state, _| { MouseEventHandler::new::<ToggleMenu, _>(0, cx, move |state, _| {
let style = theme.toolbar_dropdown_menu.header.style_for(state); let style = theme.toolbar_dropdown_menu.header.style_for(state);
Flex::row() Flex::row()
.with_child( .with_child(
@ -596,7 +596,7 @@ impl SyntaxTreeToolbarItemView {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> impl Element<Self> { ) -> impl Element<Self> {
enum ActivateLayer {} enum ActivateLayer {}
MouseEventHandler::<ActivateLayer, _>::new(layer_ix, cx, move |state, _| { MouseEventHandler::new::<ActivateLayer, _>(layer_ix, cx, move |state, _| {
let is_selected = layer.node() == active_layer.node(); let is_selected = layer.node() == active_layer.node();
let style = theme let style = theme
.toolbar_dropdown_menu .toolbar_dropdown_menu

View File

@ -434,7 +434,9 @@ impl LanguageServer {
..Default::default() ..Default::default()
}), }),
inlay_hint: Some(InlayHintClientCapabilities { inlay_hint: Some(InlayHintClientCapabilities {
resolve_support: None, resolve_support: Some(InlayHintResolveClientCapabilities {
properties: vec!["textEdits".to_string(), "tooltip".to_string()],
}),
dynamic_registration: Some(false), dynamic_registration: Some(false),
}), }),
..Default::default() ..Default::default()

View File

@ -113,7 +113,7 @@ impl<D: PickerDelegate> View for Picker<D> {
let selected_ix = this.delegate.selected_index(); let selected_ix = this.delegate.selected_index();
range.end = cmp::min(range.end, this.delegate.match_count()); range.end = cmp::min(range.end, this.delegate.match_count());
items.extend(range.map(move |ix| { items.extend(range.map(move |ix| {
MouseEventHandler::<D, _>::new(ix, cx, |state, cx| { MouseEventHandler::new::<D, _>(ix, cx, |state, cx| {
this.delegate.render_match(ix, state, ix == selected_ix, cx) this.delegate.render_match(ix, state, ix == selected_ix, cx)
}) })
// Capture mouse events // Capture mouse events

View File

@ -1954,7 +1954,7 @@ impl LspCommand for InlayHints {
_: &mut Project, _: &mut Project,
_: PeerId, _: PeerId,
buffer_version: &clock::Global, buffer_version: &clock::Global,
cx: &mut AppContext, _: &mut AppContext,
) -> proto::InlayHintsResponse { ) -> proto::InlayHintsResponse {
proto::InlayHintsResponse { proto::InlayHintsResponse {
hints: response hints: response
@ -1963,51 +1963,17 @@ impl LspCommand for InlayHints {
position: Some(language::proto::serialize_anchor(&response_hint.position)), position: Some(language::proto::serialize_anchor(&response_hint.position)),
padding_left: response_hint.padding_left, padding_left: response_hint.padding_left,
padding_right: response_hint.padding_right, padding_right: response_hint.padding_right,
label: Some(proto::InlayHintLabel {
label: Some(match response_hint.label {
InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
InlayHintLabel::LabelParts(label_parts) => {
proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
parts: label_parts.into_iter().map(|label_part| proto::InlayHintLabelPart {
value: label_part.value,
tooltip: label_part.tooltip.map(|tooltip| {
let proto_tooltip = match tooltip {
InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
kind: markup_content.kind,
value: markup_content.value,
}),
};
proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
}),
location: label_part.location.map(|location| proto::Location {
start: Some(serialize_anchor(&location.range.start)),
end: Some(serialize_anchor(&location.range.end)),
buffer_id: location.buffer.read(cx).remote_id(),
}),
}).collect()
})
}
}),
}),
kind: response_hint.kind.map(|kind| kind.name().to_string()), kind: response_hint.kind.map(|kind| kind.name().to_string()),
tooltip: response_hint.tooltip.map(|response_tooltip| { // Do not pass extra data such as tooltips to clients: host can put tooltip data from the cache during resolution.
let proto_tooltip = match response_tooltip { tooltip: None,
InlayHintTooltip::String(s) => { // Similarly, do not pass label parts to clients: host can return a detailed list during resolution.
proto::inlay_hint_tooltip::Content::Value(s) label: Some(proto::InlayHintLabel {
} label: Some(proto::inlay_hint_label::Label::Value(
InlayHintTooltip::MarkupContent(markup_content) => { match response_hint.label {
proto::inlay_hint_tooltip::Content::MarkupContent( InlayHintLabel::String(s) => s,
proto::MarkupContent { InlayHintLabel::LabelParts(_) => response_hint.text(),
kind: markup_content.kind, },
value: markup_content.value, )),
},
)
}
};
proto::InlayHintTooltip {
content: Some(proto_tooltip),
}
}), }),
}) })
.collect(), .collect(),

View File

@ -1407,7 +1407,7 @@ impl ProjectPanel {
let show_editor = details.is_editing && !details.is_processing; let show_editor = details.is_editing && !details.is_processing;
MouseEventHandler::<Self, _>::new(entry_id.to_usize(), cx, |state, cx| { MouseEventHandler::new::<Self, _>(entry_id.to_usize(), cx, |state, cx| {
let mut style = entry_style let mut style = entry_style
.in_state(details.is_selected) .in_state(details.is_selected)
.style_for(state) .style_for(state)
@ -1519,7 +1519,7 @@ impl View for ProjectPanel {
if has_worktree { if has_worktree {
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<ProjectPanel, _>::new(0, cx, |_, cx| { MouseEventHandler::new::<ProjectPanel, _>(0, cx, |_, cx| {
UniformList::new( UniformList::new(
self.list.clone(), self.list.clone(),
self.visible_entries self.visible_entries
@ -1563,7 +1563,7 @@ impl View for ProjectPanel {
} else { } else {
Flex::column() Flex::column()
.with_child( .with_child(
MouseEventHandler::<Self, _>::new(2, cx, { MouseEventHandler::new::<Self, _>(2, cx, {
let button_style = theme.open_project_button.clone(); let button_style = theme.open_project_button.clone();
let context_menu_item_style = theme::current(cx).context_menu.item.clone(); let context_menu_item_style = theme::current(cx).context_menu.item.clone();
move |state, cx| { move |state, cx| {

View File

@ -416,7 +416,7 @@ impl BufferSearchBar {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
let is_active = self.search_options.contains(option); let is_active = self.search_options.contains(option);
Some( Some(
MouseEventHandler::<Self, _>::new(option.bits as usize, cx, |state, cx| { MouseEventHandler::new::<Self, _>(option.bits as usize, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme let style = theme
.search .search
@ -463,7 +463,7 @@ impl BufferSearchBar {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
enum NavButton {} enum NavButton {}
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| { MouseEventHandler::new::<NavButton, _>(direction as usize, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme.search.option_button.inactive_state().style_for(state); let style = theme.search.option_button.inactive_state().style_for(state);
Label::new(icon, style.text.clone()) Label::new(icon, style.text.clone())
@ -497,7 +497,7 @@ impl BufferSearchBar {
let action_type_id = 0_usize; let action_type_id = 0_usize;
enum ActionButton {} enum ActionButton {}
MouseEventHandler::<ActionButton, _>::new(action_type_id, cx, |state, cx| { MouseEventHandler::new::<ActionButton, _>(action_type_id, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme.search.action_button.style_for(state); let style = theme.search.action_button.style_for(state);
Label::new(icon, style.text.clone()) Label::new(icon, style.text.clone())
@ -527,7 +527,7 @@ impl BufferSearchBar {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
enum CloseButton {} enum CloseButton {}
MouseEventHandler::<CloseButton, _>::new(0, cx, |state, _| { MouseEventHandler::new::<CloseButton, _>(0, cx, |state, _| {
let style = theme.dismiss_button.style_for(state); let style = theme.dismiss_button.style_for(state);
Svg::new("icons/x_mark_8.svg") Svg::new("icons/x_mark_8.svg")
.with_color(style.color) .with_color(style.color)

View File

@ -328,7 +328,7 @@ impl View for ProjectSearchView {
editor.set_placeholder_text(new_placeholder_text, cx); editor.set_placeholder_text(new_placeholder_text, cx);
}); });
MouseEventHandler::<Status, _>::new(0, cx, |_, _| { MouseEventHandler::new::<Status, _>(0, cx, |_, _| {
Label::new(text, theme.search.results_status.clone()) Label::new(text, theme.search.results_status.clone())
.aligned() .aligned()
.contained() .contained()
@ -1103,7 +1103,7 @@ impl ProjectSearchBar {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
enum NavButton {} enum NavButton {}
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| { MouseEventHandler::new::<NavButton, _>(direction as usize, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme.search.option_button.inactive_state().style_for(state); let style = theme.search.option_button.inactive_state().style_for(state);
Label::new(icon, style.text.clone()) Label::new(icon, style.text.clone())
@ -1134,7 +1134,7 @@ impl ProjectSearchBar {
) -> AnyElement<Self> { ) -> AnyElement<Self> {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
let is_active = self.is_option_enabled(option, cx); let is_active = self.is_option_enabled(option, cx);
MouseEventHandler::<Self, _>::new(option.bits as usize, cx, |state, cx| { MouseEventHandler::new::<Self, _>(option.bits as usize, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme let style = theme
.search .search
@ -1170,7 +1170,7 @@ impl ProjectSearchBar {
let region_id = 3; let region_id = 3;
MouseEventHandler::<Self, _>::new(region_id, cx, |state, cx| { MouseEventHandler::new::<Self, _>(region_id, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme let style = theme
.search .search

View File

@ -34,7 +34,7 @@ pub fn checkbox<Tag, V, F>(
id: usize, id: usize,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
change: F, change: F,
) -> MouseEventHandler<Tag, V> ) -> MouseEventHandler<V>
where where
Tag: 'static, Tag: 'static,
V: View, V: View,
@ -43,7 +43,7 @@ where
let label = Label::new(label, style.label.text.clone()) let label = Label::new(label, style.label.text.clone())
.contained() .contained()
.with_style(style.label.container); .with_style(style.label.container);
checkbox_with_label(label, style, checked, id, cx, change) checkbox_with_label::<Tag, _, _, _>(label, style, checked, id, cx, change)
} }
pub fn checkbox_with_label<Tag, D, V, F>( pub fn checkbox_with_label<Tag, D, V, F>(
@ -53,14 +53,14 @@ pub fn checkbox_with_label<Tag, D, V, F>(
id: usize, id: usize,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
change: F, change: F,
) -> MouseEventHandler<Tag, V> ) -> MouseEventHandler<V>
where where
Tag: 'static, Tag: 'static,
D: Element<V>, D: Element<V>,
V: View, V: View,
F: 'static + Fn(&mut V, bool, &mut EventContext<V>), F: 'static + Fn(&mut V, bool, &mut EventContext<V>),
{ {
MouseEventHandler::new(id, cx, |state, _| { MouseEventHandler::new::<Tag, _>(id, cx, |state, _| {
let indicator = if checked { let indicator = if checked {
svg(&style.icon) svg(&style.icon)
} else { } else {
@ -153,14 +153,14 @@ pub fn cta_button<Tag, L, V, F>(
style: &ButtonStyle, style: &ButtonStyle,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
f: F, f: F,
) -> MouseEventHandler<Tag, V> ) -> MouseEventHandler<V>
where where
Tag: 'static, Tag: 'static,
L: Into<Cow<'static, str>>, L: Into<Cow<'static, str>>,
V: View, V: View,
F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static, F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
{ {
MouseEventHandler::<Tag, V>::new(0, cx, |state, _| { MouseEventHandler::new::<Tag, _>(0, cx, |state, _| {
let style = style.style_for(state); let style = style.style_for(state);
Label::new(label, style.text.to_owned()) Label::new(label, style.text.to_owned())
.aligned() .aligned()
@ -215,7 +215,7 @@ where
)) ))
.with_child( .with_child(
// FIXME: Get a better tag type // FIXME: Get a better tag type
MouseEventHandler::<Tag, V>::new(999999, cx, |state, _cx| { MouseEventHandler::new::<Tag, _>(999999, cx, |state, _cx| {
let style = style.close_icon.style_for(state); let style = style.close_icon.style_for(state);
icon(style) icon(style)
}) })

View File

@ -295,7 +295,7 @@ impl PickerDelegate for BranchListDelegate {
let style = theme.picker.footer.clone(); let style = theme.picker.footer.clone();
enum BranchCreateButton {} enum BranchCreateButton {}
Some( Some(
Flex::row().with_child(MouseEventHandler::<BranchCreateButton, _>::new(0, cx, |state, _| { Flex::row().with_child(MouseEventHandler::new::<BranchCreateButton, _>(0, cx, |state, _| {
let style = style.style_for(state); let style = style.style_for(state);
Label::new("Create branch", style.label.clone()) Label::new("Create branch", style.label.clone())
.contained() .contained()

View File

@ -509,7 +509,7 @@ impl View for PanelButtons {
Some( Some(
Stack::new() Stack::new()
.with_child( .with_child(
MouseEventHandler::<Self, _>::new(panel_ix, cx, |state, cx| { MouseEventHandler::new::<Self, _>(panel_ix, cx, |state, cx| {
let style = button_style.in_state(is_active); let style = button_style.in_state(is_active);
let style = style.style_for(state); let style = style.style_for(state);

View File

@ -290,7 +290,7 @@ pub mod simple_message_notification {
.flex(1., true), .flex(1., true),
) )
.with_child( .with_child(
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| { MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
let style = theme.dismiss_button.style_for(state); let style = theme.dismiss_button.style_for(state);
Svg::new("icons/x_mark_8.svg") Svg::new("icons/x_mark_8.svg")
.with_color(style.color) .with_color(style.color)
@ -319,7 +319,7 @@ pub mod simple_message_notification {
.with_children({ .with_children({
click_message click_message
.map(|click_message| { .map(|click_message| {
MouseEventHandler::<MessageNotificationTag, _>::new( MouseEventHandler::new::<MessageNotificationTag, _>(
0, 0,
cx, cx,
|state, _| { |state, _| {

View File

@ -1211,7 +1211,7 @@ impl Pane {
enum Tab {} enum Tab {}
let mouse_event_handler = let mouse_event_handler =
MouseEventHandler::<Tab, Pane>::new(ix, cx, |_, cx| { MouseEventHandler::new::<Tab, _>(ix, cx, |_, cx| {
Self::render_tab( Self::render_tab(
&item, &item,
pane.clone(), pane.clone(),
@ -1420,7 +1420,7 @@ impl Pane {
let item_id = item.id(); let item_id = item.id();
enum TabCloseButton {} enum TabCloseButton {}
let icon = Svg::new("icons/x_mark_8.svg"); let icon = Svg::new("icons/x_mark_8.svg");
MouseEventHandler::<TabCloseButton, _>::new(item_id, cx, |mouse_state, _| { MouseEventHandler::new::<TabCloseButton, _>(item_id, cx, |mouse_state, _| {
if mouse_state.hovered() { if mouse_state.hovered() {
icon.with_color(tab_style.icon_close_active) icon.with_color(tab_style.icon_close_active)
} else { } else {
@ -1485,7 +1485,7 @@ impl Pane {
) -> AnyElement<Pane> { ) -> AnyElement<Pane> {
enum TabBarButton {} enum TabBarButton {}
let mut button = MouseEventHandler::<TabBarButton, _>::new(index, cx, |mouse_state, cx| { let mut button = MouseEventHandler::new::<TabBarButton, _>(index, cx, |mouse_state, cx| {
let theme = &settings::get::<ThemeSettings>(cx).theme.workspace.tab_bar; let theme = &settings::get::<ThemeSettings>(cx).theme.workspace.tab_bar;
let style = theme.pane_button.in_state(is_active).style_for(mouse_state); let style = theme.pane_button.in_state(is_active).style_for(mouse_state);
Svg::new(icon) Svg::new(icon)
@ -1547,7 +1547,7 @@ impl View for Pane {
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> { fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
enum MouseNavigationHandler {} enum MouseNavigationHandler {}
MouseEventHandler::<MouseNavigationHandler, _>::new(0, cx, |_, cx| { MouseEventHandler::new::<MouseNavigationHandler, _>(0, cx, |_, cx| {
let active_item_index = self.active_item_index; let active_item_index = self.active_item_index;
if let Some(active_item) = self.active_item() { if let Some(active_item) = self.active_item() {
@ -1559,7 +1559,7 @@ impl View for Pane {
enum TabBarEventHandler {} enum TabBarEventHandler {}
stack.add_child( stack.add_child(
MouseEventHandler::<TabBarEventHandler, _>::new(0, cx, |_, _| { MouseEventHandler::new::<TabBarEventHandler, _>(0, cx, |_, _| {
Empty::new() Empty::new()
.contained() .contained()
.with_style(theme.workspace.tab_bar.container) .with_style(theme.workspace.tab_bar.container)

View File

@ -19,7 +19,7 @@ pub fn dragged_item_receiver<Tag, D, F>(
split_margin: Option<f32>, split_margin: Option<f32>,
cx: &mut ViewContext<Pane>, cx: &mut ViewContext<Pane>,
render_child: F, render_child: F,
) -> MouseEventHandler<Tag, Pane> ) -> MouseEventHandler<Pane>
where where
Tag: 'static, Tag: 'static,
D: Element<Pane>, D: Element<Pane>,
@ -39,7 +39,7 @@ where
None None
}; };
let mut handler = MouseEventHandler::<Tag, _>::above(region_id, cx, |state, cx| { let mut handler = MouseEventHandler::above::<Tag, _>(region_id, cx, |state, cx| {
// Observing hovered will cause a render when the mouse enters regardless // Observing hovered will cause a render when the mouse enters regardless
// of if mouse position was accessed before // of if mouse position was accessed before
let drag_position = if state.hovered() { drag_position } else { None }; let drag_position = if state.hovered() { drag_position } else { None };

View File

@ -212,7 +212,7 @@ impl Member {
let leader_user_id = leader.user.id; let leader_user_id = leader.user.id;
let app_state = Arc::downgrade(app_state); let app_state = Arc::downgrade(app_state);
Some( Some(
MouseEventHandler::<FollowIntoExternalProject, _>::new( MouseEventHandler::new::<FollowIntoExternalProject, _>(
pane.id(), pane.id(),
cx, cx,
|_, _| { |_, _| {

View File

@ -72,7 +72,7 @@ impl View for SharedScreen {
enum Focus {} enum Focus {}
let frame = self.frame.clone(); let frame = self.frame.clone();
MouseEventHandler::<Focus, _>::new(0, cx, |_, cx| { MouseEventHandler::new::<Focus, _>(0, cx, |_, cx| {
Canvas::new(move |scene, bounds, _, _, _| { Canvas::new(move |scene, bounds, _, _, _| {
if let Some(frame) = frame.clone() { if let Some(frame) = frame.clone() {
let size = constrain_size_preserving_aspect_ratio( let size = constrain_size_preserving_aspect_ratio(

View File

@ -223,7 +223,7 @@ fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>
action_name: &'static str, action_name: &'static str,
cx: &mut ViewContext<Toolbar>, cx: &mut ViewContext<Toolbar>,
) -> AnyElement<Toolbar> { ) -> AnyElement<Toolbar> {
MouseEventHandler::<A, _>::new(0, cx, |state, _| { MouseEventHandler::new::<A, _>(0, cx, |state, _| {
let style = if enabled { let style = if enabled {
style.style_for(state) style.style_for(state)
} else { } else {

View File

@ -2564,7 +2564,7 @@ impl Workspace {
}; };
enum TitleBar {} enum TitleBar {}
MouseEventHandler::<TitleBar, _>::new(0, cx, |_, cx| { MouseEventHandler::new::<TitleBar, _>(0, cx, |_, cx| {
Stack::new() Stack::new()
.with_children( .with_children(
self.titlebar_item self.titlebar_item
@ -2653,7 +2653,7 @@ impl Workspace {
if self.project.read(cx).is_read_only() { if self.project.read(cx).is_read_only() {
enum DisconnectedOverlay {} enum DisconnectedOverlay {}
Some( Some(
MouseEventHandler::<DisconnectedOverlay, _>::new(0, cx, |_, cx| { MouseEventHandler::new::<DisconnectedOverlay, _>(0, cx, |_, cx| {
let theme = &theme::current(cx); let theme = &theme::current(cx);
Label::new( Label::new(
"Your connection to the remote project has been lost.", "Your connection to the remote project has been lost.",
@ -3763,7 +3763,7 @@ impl View for Workspace {
// Prevent clicks within the modal from falling // Prevent clicks within the modal from falling
// through to the rest of the workspace. // through to the rest of the workspace.
enum ModalBackground {} enum ModalBackground {}
MouseEventHandler::<ModalBackground, _>::new( MouseEventHandler::new::<ModalBackground, _>(
0, 0,
cx, cx,
|_, cx| ChildView::new(modal.view.as_any(), cx), |_, cx| ChildView::new(modal.view.as_any(), cx),