mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 04:20:46 +00:00
Add components example (#2846)
This PR is a continuation of the components UI exploration I've been doing. It adds an example to the GPUI examples page and totally restructures the generics on our MouseEventHandler. Release Note: - N/A
This commit is contained in:
commit
22da42fc69
49 changed files with 585 additions and 155 deletions
|
@ -318,7 +318,7 @@ impl View for ActivityIndicator {
|
|||
on_click,
|
||||
} = 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 style = if state.hovered() && on_click.is_some() {
|
||||
theme.hovered.as_ref().unwrap_or(&theme.default)
|
||||
|
|
|
@ -348,7 +348,7 @@ impl AssistantPanel {
|
|||
enum History {}
|
||||
let theme = theme::current(cx);
|
||||
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);
|
||||
Svg::for_style(style.icon.clone())
|
||||
.contained()
|
||||
|
@ -380,7 +380,7 @@ impl AssistantPanel {
|
|||
fn render_split_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
|
||||
let theme = theme::current(cx);
|
||||
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);
|
||||
Svg::for_style(style.icon.clone())
|
||||
.contained()
|
||||
|
@ -404,7 +404,7 @@ impl AssistantPanel {
|
|||
fn render_assist_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
|
||||
let theme = theme::current(cx);
|
||||
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);
|
||||
Svg::for_style(style.icon.clone())
|
||||
.contained()
|
||||
|
@ -422,7 +422,7 @@ impl AssistantPanel {
|
|||
fn render_quote_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
|
||||
let theme = theme::current(cx);
|
||||
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);
|
||||
Svg::for_style(style.icon.clone())
|
||||
.contained()
|
||||
|
@ -450,7 +450,7 @@ impl AssistantPanel {
|
|||
fn render_plus_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
|
||||
let theme = theme::current(cx);
|
||||
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);
|
||||
Svg::for_style(style.icon.clone())
|
||||
.contained()
|
||||
|
@ -480,7 +480,7 @@ impl AssistantPanel {
|
|||
&theme.assistant.zoom_in_button
|
||||
};
|
||||
|
||||
MouseEventHandler::<ToggleZoomButton, _>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<ToggleZoomButton, _>(0, cx, |state, _| {
|
||||
let style = style.style_for(state);
|
||||
Svg::for_style(style.icon.clone())
|
||||
.contained()
|
||||
|
@ -506,7 +506,7 @@ impl AssistantPanel {
|
|||
) -> impl Element<Self> {
|
||||
let conversation = &self.saved_conversations[index];
|
||||
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;
|
||||
Flex::row()
|
||||
.with_child(
|
||||
|
@ -1818,7 +1818,7 @@ impl ConversationEditor {
|
|||
let theme = theme::current(cx);
|
||||
let style = &theme.assistant;
|
||||
let message_id = message.id;
|
||||
let sender = MouseEventHandler::<Sender, _>::new(
|
||||
let sender = MouseEventHandler::new::<Sender, _>(
|
||||
message_id.0,
|
||||
cx,
|
||||
|state, _| match message.role {
|
||||
|
@ -2044,7 +2044,7 @@ impl ConversationEditor {
|
|||
) -> impl Element<Self> {
|
||||
enum Model {}
|
||||
|
||||
MouseEventHandler::<Model, _>::new(0, cx, |state, cx| {
|
||||
MouseEventHandler::new::<Model, _>(0, cx, |state, cx| {
|
||||
let style = style.model.style_for(state);
|
||||
Label::new(self.conversation.read(cx).model.clone(), style.text.clone())
|
||||
.contained()
|
||||
|
|
|
@ -31,7 +31,7 @@ impl View for UpdateNotification {
|
|||
|
||||
let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||
|
||||
MouseEventHandler::<ViewReleaseNotes, _>::new(0, cx, |state, cx| {
|
||||
MouseEventHandler::new::<ViewReleaseNotes, _>(0, cx, |state, cx| {
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::row()
|
||||
|
@ -48,7 +48,7 @@ impl View for UpdateNotification {
|
|||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
|
||||
let style = theme.dismiss_button.style_for(state);
|
||||
Svg::new("icons/x_mark_8.svg")
|
||||
.with_color(style.color)
|
||||
|
|
|
@ -82,7 +82,7 @@ impl View for Breadcrumbs {
|
|||
.into_any();
|
||||
}
|
||||
|
||||
MouseEventHandler::<Breadcrumbs, Breadcrumbs>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<Breadcrumbs, _>(0, cx, |state, _| {
|
||||
let style = style.style_for(state);
|
||||
crumbs.with_style(style.container)
|
||||
})
|
||||
|
|
|
@ -226,7 +226,7 @@ impl CollabTitlebarItem {
|
|||
let mut ret = Flex::row().with_child(
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<ToggleProjectMenu, Self>::new(0, cx, |mouse_state, cx| {
|
||||
MouseEventHandler::new::<ToggleProjectMenu, _>(0, cx, |mouse_state, cx| {
|
||||
let style = project_style
|
||||
.in_state(self.project_popover.is_some())
|
||||
.style_for(mouse_state);
|
||||
|
@ -266,7 +266,7 @@ impl CollabTitlebarItem {
|
|||
.with_child(
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<ToggleVcsMenu, Self>::new(
|
||||
MouseEventHandler::new::<ToggleVcsMenu, _>(
|
||||
0,
|
||||
cx,
|
||||
|mouse_state, cx| {
|
||||
|
@ -398,7 +398,7 @@ impl CollabTitlebarItem {
|
|||
self.branch_popover.as_ref().map(|child| {
|
||||
let theme = theme::current(cx).clone();
|
||||
let child = ChildView::new(child, cx);
|
||||
let child = MouseEventHandler::<BranchList, Self>::new(0, cx, |_, _| {
|
||||
let child = MouseEventHandler::new::<BranchList, _>(0, cx, |_, _| {
|
||||
child
|
||||
.flex(1., true)
|
||||
.contained()
|
||||
|
@ -433,7 +433,7 @@ impl CollabTitlebarItem {
|
|||
self.project_popover.as_ref().map(|child| {
|
||||
let theme = theme::current(cx).clone();
|
||||
let child = ChildView::new(child, cx);
|
||||
let child = MouseEventHandler::<RecentProjects, Self>::new(0, cx, |_, _| {
|
||||
let child = MouseEventHandler::new::<RecentProjects, _>(0, cx, |_, _| {
|
||||
child
|
||||
.flex(1., true)
|
||||
.contained()
|
||||
|
@ -560,7 +560,7 @@ impl CollabTitlebarItem {
|
|||
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<ToggleContactsMenu, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<ToggleContactsMenu, _>(0, cx, |state, _| {
|
||||
let style = titlebar
|
||||
.toggle_contacts_button
|
||||
.in_state(self.contacts_popover.is_some())
|
||||
|
@ -610,7 +610,7 @@ impl CollabTitlebarItem {
|
|||
|
||||
let active = room.read(cx).is_screen_sharing();
|
||||
let titlebar = &theme.titlebar;
|
||||
MouseEventHandler::<ToggleScreenSharing, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<ToggleScreenSharing, _>(0, cx, |state, _| {
|
||||
let style = titlebar
|
||||
.screen_share_button
|
||||
.in_state(active)
|
||||
|
@ -659,7 +659,7 @@ impl CollabTitlebarItem {
|
|||
}
|
||||
|
||||
let titlebar = &theme.titlebar;
|
||||
MouseEventHandler::<ToggleMute, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<ToggleMute, _>(0, cx, |state, _| {
|
||||
let style = titlebar
|
||||
.toggle_microphone_button
|
||||
.in_state(is_muted)
|
||||
|
@ -712,7 +712,7 @@ impl CollabTitlebarItem {
|
|||
}
|
||||
|
||||
let titlebar = &theme.titlebar;
|
||||
MouseEventHandler::<ToggleDeafen, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<ToggleDeafen, _>(0, cx, |state, _| {
|
||||
let style = titlebar
|
||||
.toggle_speakers_button
|
||||
.in_state(is_deafened)
|
||||
|
@ -747,7 +747,7 @@ impl CollabTitlebarItem {
|
|||
let tooltip = "Leave call";
|
||||
|
||||
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);
|
||||
Svg::new(icon)
|
||||
.with_color(style.color)
|
||||
|
@ -801,7 +801,7 @@ impl CollabTitlebarItem {
|
|||
Some(
|
||||
Stack::new()
|
||||
.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
|
||||
let style = titlebar.share_button.inactive_state().style_for(state);
|
||||
Label::new(label, style.text.clone())
|
||||
|
@ -847,7 +847,7 @@ impl CollabTitlebarItem {
|
|||
let avatar_style = &user_menu_button_style.avatar;
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<ToggleUserMenu, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<ToggleUserMenu, _>(0, cx, |state, _| {
|
||||
let style = user_menu_button_style
|
||||
.user_menu
|
||||
.inactive_state()
|
||||
|
@ -907,7 +907,7 @@ impl CollabTitlebarItem {
|
|||
|
||||
fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
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);
|
||||
Label::new("Sign In", style.text.clone())
|
||||
.contained()
|
||||
|
@ -1142,7 +1142,7 @@ impl CollabTitlebarItem {
|
|||
if let Some(replica_id) = replica_id {
|
||||
enum ToggleFollow {}
|
||||
|
||||
content = MouseEventHandler::<ToggleFollow, Self>::new(
|
||||
content = MouseEventHandler::new::<ToggleFollow, _>(
|
||||
replica_id.into(),
|
||||
cx,
|
||||
move |_, _| content,
|
||||
|
@ -1173,7 +1173,7 @@ impl CollabTitlebarItem {
|
|||
enum JoinProject {}
|
||||
|
||||
let user_id = user.id;
|
||||
content = MouseEventHandler::<JoinProject, Self>::new(
|
||||
content = MouseEventHandler::new::<JoinProject, _>(
|
||||
peer_id.as_u64() as usize,
|
||||
cx,
|
||||
move |_, _| content,
|
||||
|
@ -1261,7 +1261,7 @@ impl CollabTitlebarItem {
|
|||
.into_any(),
|
||||
),
|
||||
client::Status::UpgradeRequired => Some(
|
||||
MouseEventHandler::<ConnectionStatusButton, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<ConnectionStatusButton, _>(0, cx, |_, _| {
|
||||
Label::new(
|
||||
"Please update Zed to collaborate",
|
||||
theme.titlebar.outdated_warning.text.clone(),
|
||||
|
|
|
@ -810,7 +810,7 @@ impl ContactList {
|
|||
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 row = theme
|
||||
.project_row
|
||||
|
@ -904,7 +904,7 @@ impl ContactList {
|
|||
let baseline_offset =
|
||||
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,
|
||||
cx,
|
||||
|mouse_state, _| {
|
||||
|
@ -1006,7 +1006,7 @@ impl ContactList {
|
|||
};
|
||||
let leave_call = if section == Section::ActiveCall {
|
||||
Some(
|
||||
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<LeaveCallContactList, _>(0, cx, |state, _| {
|
||||
let style = theme.leave_call.style_for(state);
|
||||
Label::new("Leave Call", style.text.clone())
|
||||
.contained()
|
||||
|
@ -1024,7 +1024,7 @@ impl ContactList {
|
|||
};
|
||||
|
||||
let icon_size = theme.section_icon_size;
|
||||
MouseEventHandler::<Header, Self>::new(section as usize, cx, |_, _| {
|
||||
MouseEventHandler::new::<Header, _>(section as usize, cx, |_, _| {
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Svg::new(if is_collapsed {
|
||||
|
@ -1075,7 +1075,7 @@ impl ContactList {
|
|||
let github_login = contact.user.github_login.clone();
|
||||
let initial_project = project.clone();
|
||||
let mut event_handler =
|
||||
MouseEventHandler::<Contact, Self>::new(contact.user.id as usize, cx, |_, cx| {
|
||||
MouseEventHandler::new::<Contact, _>(contact.user.id as usize, cx, |_, cx| {
|
||||
Flex::row()
|
||||
.with_children(contact.user.avatar.clone().map(|avatar| {
|
||||
let status_badge = if contact.online {
|
||||
|
@ -1114,7 +1114,7 @@ impl ContactList {
|
|||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<Cancel, Self>::new(
|
||||
MouseEventHandler::new::<Cancel, _>(
|
||||
contact.user.id as usize,
|
||||
cx,
|
||||
|mouse_state, _| {
|
||||
|
@ -1208,7 +1208,7 @@ impl ContactList {
|
|||
|
||||
if is_incoming {
|
||||
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 {
|
||||
&theme.disabled_button
|
||||
} else {
|
||||
|
@ -1231,7 +1231,7 @@ impl ContactList {
|
|||
);
|
||||
|
||||
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 {
|
||||
&theme.disabled_button
|
||||
} else {
|
||||
|
@ -1254,7 +1254,7 @@ impl ContactList {
|
|||
);
|
||||
} else {
|
||||
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 {
|
||||
&theme.disabled_button
|
||||
} else {
|
||||
|
@ -1333,7 +1333,7 @@ impl View for ContactList {
|
|||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<AddContact, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<AddContact, _>(0, cx, |_, _| {
|
||||
render_icon_button(
|
||||
&theme.contact_list.add_contact_button,
|
||||
"icons/user_plus_16.svg",
|
||||
|
|
|
@ -113,7 +113,7 @@ impl View for ContactsPopover {
|
|||
Child::ContactFinder(child) => ChildView::new(child, cx),
|
||||
};
|
||||
|
||||
MouseEventHandler::<ContactsPopover, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<ContactsPopover, _>(0, cx, |_, _| {
|
||||
Flex::column()
|
||||
.with_child(child.flex(1., true))
|
||||
.contained()
|
||||
|
|
|
@ -173,7 +173,7 @@ impl IncomingCallNotification {
|
|||
let theme = theme::current(cx);
|
||||
Flex::column()
|
||||
.with_child(
|
||||
MouseEventHandler::<Accept, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<Accept, _>(0, cx, |_, _| {
|
||||
let theme = &theme.incoming_call_notification;
|
||||
Label::new("Accept", theme.accept_button.text.clone())
|
||||
.aligned()
|
||||
|
@ -187,7 +187,7 @@ impl IncomingCallNotification {
|
|||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<Decline, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<Decline, _>(0, cx, |_, _| {
|
||||
let theme = &theme.incoming_call_notification;
|
||||
Label::new("Decline", theme.decline_button.text.clone())
|
||||
.aligned()
|
||||
|
|
|
@ -52,7 +52,7 @@ where
|
|||
.flex(1., true),
|
||||
)
|
||||
.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);
|
||||
Svg::new("icons/x_mark_8.svg")
|
||||
.with_color(style.color)
|
||||
|
@ -92,7 +92,7 @@ where
|
|||
Flex::row()
|
||||
.with_children(buttons.into_iter().enumerate().map(
|
||||
|(ix, (message, handler))| {
|
||||
MouseEventHandler::<Button, V>::new(ix, cx, |state, _| {
|
||||
MouseEventHandler::new::<Button, _>(ix, cx, |state, _| {
|
||||
let button = theme.button.style_for(state);
|
||||
Label::new(message, button.text.clone())
|
||||
.contained()
|
||||
|
|
|
@ -170,7 +170,7 @@ impl ProjectSharedNotification {
|
|||
let theme = theme::current(cx);
|
||||
Flex::column()
|
||||
.with_child(
|
||||
MouseEventHandler::<Open, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<Open, _>(0, cx, |_, _| {
|
||||
let theme = &theme.project_shared_notification;
|
||||
Label::new("Open", theme.open_button.text.clone())
|
||||
.aligned()
|
||||
|
@ -182,7 +182,7 @@ impl ProjectSharedNotification {
|
|||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<Dismiss, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<Dismiss, _>(0, cx, |_, _| {
|
||||
let theme = &theme.project_shared_notification;
|
||||
Label::new("Dismiss", theme.dismiss_button.text.clone())
|
||||
.aligned()
|
||||
|
|
|
@ -47,7 +47,7 @@ impl View for SharingStatusIndicator {
|
|||
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")
|
||||
.with_color(color)
|
||||
.constrained()
|
||||
|
|
|
@ -439,14 +439,14 @@ impl ContextMenu {
|
|||
|
||||
let style = theme::current(cx).context_menu.clone();
|
||||
|
||||
MouseEventHandler::<Menu, ContextMenu>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::new::<Menu, _>(0, cx, |_, cx| {
|
||||
Flex::column()
|
||||
.with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
||||
match item {
|
||||
ContextMenuItem::Item { label, action } => {
|
||||
let action = action.clone();
|
||||
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.style_for(state);
|
||||
let keystroke = match &action {
|
||||
|
|
|
@ -113,7 +113,7 @@ impl CopilotCodeVerification {
|
|||
|
||||
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()
|
||||
.with_child(
|
||||
Label::new(data.user_code.clone(), device_code_style.text.clone())
|
||||
|
|
|
@ -62,7 +62,7 @@ impl View for CopilotButton {
|
|||
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<Self, _>::new(0, cx, {
|
||||
MouseEventHandler::new::<Self, _>(0, cx, {
|
||||
let theme = theme.clone();
|
||||
let status = status.clone();
|
||||
move |state, _cx| {
|
||||
|
|
|
@ -94,7 +94,7 @@ impl View for DiagnosticIndicator {
|
|||
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||
let in_progress = !self.in_progress_checks.is_empty();
|
||||
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 style = theme
|
||||
.workspace
|
||||
|
@ -195,7 +195,7 @@ impl View for DiagnosticIndicator {
|
|||
} else if let Some(diagnostic) = &self.current_diagnostic {
|
||||
let message_style = style.diagnostic_message.clone();
|
||||
element.add_child(
|
||||
MouseEventHandler::<Message, _>::new(1, cx, |state, _| {
|
||||
MouseEventHandler::new::<Message, _>(1, cx, |state, _| {
|
||||
Label::new(
|
||||
diagnostic.message.split('\n').next().unwrap().to_string(),
|
||||
message_style.style_for(state).text.clone(),
|
||||
|
|
|
@ -202,7 +202,7 @@ impl<V: View> DragAndDrop<V> {
|
|||
let position = (position - region_offset).round();
|
||||
Some(
|
||||
Overlay::new(
|
||||
MouseEventHandler::<DraggedElementHandler, V>::new(
|
||||
MouseEventHandler::new::<DraggedElementHandler, _>(
|
||||
0,
|
||||
cx,
|
||||
|_, cx| render(payload, cx),
|
||||
|
@ -235,7 +235,7 @@ impl<V: View> DragAndDrop<V> {
|
|||
}
|
||||
|
||||
State::Canceled => Some(
|
||||
MouseEventHandler::<DraggedElementHandler, V>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<DraggedElementHandler, _>(0, cx, |_, _| {
|
||||
Empty::new().constrained().with_width(0.).with_height(0.)
|
||||
})
|
||||
.on_up(MouseButton::Left, |_, _, cx| {
|
||||
|
@ -301,7 +301,7 @@ pub trait Draggable<V: View> {
|
|||
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>(
|
||||
self,
|
||||
payload: P,
|
||||
|
|
|
@ -867,7 +867,7 @@ impl CompletionsMenu {
|
|||
let completion = &completions[mat.candidate_id];
|
||||
let item_ix = start_ix + ix;
|
||||
items.push(
|
||||
MouseEventHandler::<CompletionTag, _>::new(
|
||||
MouseEventHandler::new::<CompletionTag, _>(
|
||||
mat.candidate_id,
|
||||
cx,
|
||||
|state, _| {
|
||||
|
@ -1044,7 +1044,7 @@ impl CodeActionsMenu {
|
|||
for (ix, action) in actions[range].iter().enumerate() {
|
||||
let item_ix = start_ix + ix;
|
||||
items.push(
|
||||
MouseEventHandler::<ActionTag, _>::new(item_ix, cx, |state, _| {
|
||||
MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
|
||||
let item_style = if item_ix == selected_item {
|
||||
style.autocomplete.selected_item
|
||||
} else if state.hovered() {
|
||||
|
@ -3547,7 +3547,7 @@ impl Editor {
|
|||
if self.available_code_actions.is_some() {
|
||||
enum CodeActions {}
|
||||
Some(
|
||||
MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
|
||||
Svg::new("icons/bolt_8.svg").with_color(
|
||||
style
|
||||
.code_actions
|
||||
|
@ -3594,7 +3594,7 @@ impl Editor {
|
|||
fold_data
|
||||
.map(|(fold_status, buffer_row, active)| {
|
||||
(active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
|
||||
MouseEventHandler::<FoldIndicators, _>::new(
|
||||
MouseEventHandler::new::<FoldIndicators, _>(
|
||||
ix as usize,
|
||||
cx,
|
||||
|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 anchor_x = cx.anchor_x;
|
||||
enum BlockContextToolip {}
|
||||
MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
|
||||
MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
|
||||
Flex::column()
|
||||
.with_children(highlighted_lines.iter().map(|(line, highlights)| {
|
||||
Label::new(
|
||||
|
|
|
@ -1637,7 +1637,7 @@ impl EditorElement {
|
|||
let jump_position = language::ToPoint::to_point(&jump_anchor, buffer);
|
||||
|
||||
enum JumpIcon {}
|
||||
MouseEventHandler::<JumpIcon, _>::new((*id).into(), cx, |state, _| {
|
||||
MouseEventHandler::new::<JumpIcon, _>((*id).into(), cx, |state, _| {
|
||||
let style = style.jump_icon.style_for(state);
|
||||
Svg::new("icons/arrow_up_right_8.svg")
|
||||
.with_color(style.color)
|
||||
|
|
|
@ -565,7 +565,7 @@ impl InfoPopover {
|
|||
)
|
||||
});
|
||||
|
||||
MouseEventHandler::<InfoPopover, _>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::new::<InfoPopover, _>(0, cx, |_, cx| {
|
||||
let mut region_id = 0;
|
||||
let view_id = cx.view_id();
|
||||
|
||||
|
@ -654,7 +654,7 @@ impl DiagnosticPopover {
|
|||
|
||||
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||
|
||||
MouseEventHandler::<DiagnosticPopover, _>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<DiagnosticPopover, _>(0, cx, |_, _| {
|
||||
text.with_soft_wrap(true)
|
||||
.contained()
|
||||
.with_style(container_style)
|
||||
|
|
|
@ -35,7 +35,7 @@ impl View for DeployFeedbackButton {
|
|||
let theme = theme::current(cx).clone();
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<Self, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<Self, _>(0, cx, |state, _| {
|
||||
let style = &theme
|
||||
.workspace
|
||||
.status_bar
|
||||
|
|
|
@ -41,7 +41,7 @@ impl View for FeedbackInfoText {
|
|||
.aligned(),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<OpenZedCommunityRepo, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<OpenZedCommunityRepo, _>(0, cx, |state, _| {
|
||||
let contained_text = if state.hovered() {
|
||||
&theme.feedback.link_text_hover
|
||||
} else {
|
||||
|
|
|
@ -52,7 +52,7 @@ impl View for SubmitFeedbackButton {
|
|||
.map_or(true, |i| i.read(cx).allow_submission);
|
||||
|
||||
enum SubmitFeedbackButton {}
|
||||
MouseEventHandler::<SubmitFeedbackButton, Self>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<SubmitFeedbackButton, _>(0, cx, |state, _| {
|
||||
let text;
|
||||
let style = if allow_submission {
|
||||
text = "Submit as Markdown";
|
||||
|
|
335
crates/gpui/examples/components.rs
Normal file
335
crates/gpui/examples/components.rs
Normal 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!()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3280,7 +3280,11 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
|
|||
}
|
||||
|
||||
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 {
|
||||
hovered: self.window.hovered_region_ids.contains(®ion_id),
|
||||
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> {
|
||||
fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
|
||||
BorrowAppContext::read_with(&*self.window_context, f)
|
||||
|
@ -5171,7 +5205,7 @@ mod tests {
|
|||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
enum Handler {}
|
||||
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 |_, _, _| {
|
||||
mouse_down_count.fetch_add(1, SeqCst);
|
||||
})
|
||||
|
|
|
@ -193,11 +193,11 @@ pub trait Element<V: View>: 'static {
|
|||
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
|
||||
Self: Sized,
|
||||
{
|
||||
MouseEventHandler::for_child(self.into_any(), region_id)
|
||||
MouseEventHandler::for_child::<Tag>(self.into_any(), region_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,15 @@ pub struct ContainerStyle {
|
|||
pub cursor: Option<CursorStyle>,
|
||||
}
|
||||
|
||||
impl ContainerStyle {
|
||||
pub fn fill(color: Color) -> Self {
|
||||
Self {
|
||||
background_color: Some(color),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Container<V: View> {
|
||||
child: AnyElement<V>,
|
||||
style: ContainerStyle,
|
||||
|
|
|
@ -11,12 +11,12 @@ use crate::{
|
|||
MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
|
||||
},
|
||||
AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, PaintContext,
|
||||
SceneBuilder, SizeConstraint, View, ViewContext,
|
||||
SceneBuilder, SizeConstraint, TypeTag, View, ViewContext,
|
||||
};
|
||||
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>,
|
||||
region_id: usize,
|
||||
cursor_style: Option<CursorStyle>,
|
||||
|
@ -26,13 +26,13 @@ pub struct MouseEventHandler<Tag: 'static, V: View> {
|
|||
notify_on_click: bool,
|
||||
above: bool,
|
||||
padding: Padding,
|
||||
_tag: PhantomData<Tag>,
|
||||
tag: TypeTag,
|
||||
}
|
||||
|
||||
/// Element which provides a render_child callback with a MouseState and paints a mouse
|
||||
/// region under (or above) it for easy mouse event handling.
|
||||
impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
||||
pub fn for_child(child: impl Element<V>, region_id: usize) -> Self {
|
||||
impl<V: View> MouseEventHandler<V> {
|
||||
pub fn for_child<Tag: 'static>(child: impl Element<V>, region_id: usize) -> Self {
|
||||
Self {
|
||||
child: child.into_any(),
|
||||
region_id,
|
||||
|
@ -43,16 +43,19 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
hoverable: false,
|
||||
above: false,
|
||||
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
|
||||
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 notify_on_hover = mouse_state.accessed_hovered();
|
||||
let notify_on_click = mouse_state.accessed_clicked();
|
||||
|
@ -66,19 +69,46 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
hoverable: true,
|
||||
above: false,
|
||||
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
|
||||
/// for drag and drop handling and similar events which should be captured before the child
|
||||
/// 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
|
||||
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
|
||||
}
|
||||
|
@ -223,7 +253,8 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
});
|
||||
}
|
||||
scene.push_mouse_region(
|
||||
MouseRegion::from_handlers::<Tag>(
|
||||
MouseRegion::from_handlers(
|
||||
self.tag,
|
||||
cx.view_id(),
|
||||
self.region_id,
|
||||
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 PaintState = ();
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ impl<V: View> Tooltip<V> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let child = MouseEventHandler::<MouseEventHandlerState<Tag>, _>::new(id, cx, |_, _| child)
|
||||
let child = MouseEventHandler::new::<MouseEventHandlerState<Tag>, _>(id, cx, |_, _| child)
|
||||
.on_hover(move |e, _, cx| {
|
||||
let position = e.position;
|
||||
if e.started {
|
||||
|
|
|
@ -72,6 +72,13 @@ pub struct TextStyle {
|
|||
}
|
||||
|
||||
impl TextStyle {
|
||||
pub fn for_color(color: Color) -> Self {
|
||||
Self {
|
||||
color,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refine(self, refinement: TextStyleRefinement) -> TextStyle {
|
||||
TextStyle {
|
||||
color: refinement.color.unwrap_or(self.color),
|
||||
|
|
|
@ -24,6 +24,7 @@ use crate::{
|
|||
use anyhow::{anyhow, bail, Result};
|
||||
use async_task::Runnable;
|
||||
pub use event::*;
|
||||
use pathfinder_geometry::vector::vec2f;
|
||||
use postage::oneshot;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
|
@ -180,6 +181,16 @@ pub struct WindowOptions<'a> {
|
|||
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)]
|
||||
pub struct TitlebarOptions<'a> {
|
||||
pub title: Option<&'a str>,
|
||||
|
|
|
@ -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 pathfinder_geometry::rect::RectF;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
fmt::Debug,
|
||||
mem::Discriminant,
|
||||
rc::Rc,
|
||||
};
|
||||
use std::{any::Any, fmt::Debug, mem::Discriminant, rc::Rc};
|
||||
|
||||
use super::{
|
||||
mouse_event::{
|
||||
|
@ -33,14 +30,27 @@ impl MouseRegion {
|
|||
/// should pass a different (consistent) region_id. If you have one big region that covers your
|
||||
/// whole component, just pass the view_id again.
|
||||
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 {
|
||||
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,
|
||||
region_id: usize,
|
||||
bounds: RectF,
|
||||
|
@ -49,10 +59,8 @@ impl MouseRegion {
|
|||
Self {
|
||||
id: MouseRegionId {
|
||||
view_id,
|
||||
tag: TypeId::of::<Tag>(),
|
||||
tag,
|
||||
region_id,
|
||||
#[cfg(debug_assertions)]
|
||||
tag_type_name: std::any::type_name::<Tag>(),
|
||||
},
|
||||
bounds,
|
||||
handlers,
|
||||
|
@ -180,20 +188,16 @@ impl MouseRegion {
|
|||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)]
|
||||
pub struct MouseRegionId {
|
||||
view_id: usize,
|
||||
tag: TypeId,
|
||||
tag: TypeTag,
|
||||
region_id: usize,
|
||||
#[cfg(debug_assertions)]
|
||||
tag_type_name: &'static str,
|
||||
}
|
||||
|
||||
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 {
|
||||
view_id,
|
||||
region_id,
|
||||
tag: TypeId::of::<Tag>(),
|
||||
#[cfg(debug_assertions)]
|
||||
tag_type_name: std::any::type_name::<Tag>(),
|
||||
tag,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +207,7 @@ impl MouseRegionId {
|
|||
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn tag_type_name(&self) -> &'static str {
|
||||
self.tag_type_name
|
||||
self.tag.type_name()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ impl View for Select {
|
|||
Default::default()
|
||||
};
|
||||
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.selected_item_ix,
|
||||
ItemType::Header,
|
||||
|
@ -130,7 +130,7 @@ impl View for Select {
|
|||
let selected_item_ix = this.selected_item_ix;
|
||||
range.end = range.end.min(this.item_count);
|
||||
items.extend(range.map(|ix| {
|
||||
MouseEventHandler::<Item, _>::new(ix, cx, |mouse_state, cx| {
|
||||
MouseEventHandler::new::<Item, _>(ix, cx, |mouse_state, cx| {
|
||||
(this.render_item)(
|
||||
ix,
|
||||
if ix == selected_item_ix {
|
||||
|
|
|
@ -53,7 +53,7 @@ impl View for ActiveBufferLanguage {
|
|||
"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 style = theme.active_language.style_for(state);
|
||||
Label::new(active_language_text, style.text.clone())
|
||||
|
|
|
@ -573,7 +573,7 @@ impl View for LspLogToolbarItemView {
|
|||
.with_children(if self.menu_open {
|
||||
Some(
|
||||
Overlay::new(
|
||||
MouseEventHandler::<Menu, _>::new(0, cx, move |_, cx| {
|
||||
MouseEventHandler::new::<Menu, _>(0, cx, move |_, cx| {
|
||||
Flex::column()
|
||||
.with_children(menu_rows.into_iter().map(|row| {
|
||||
Self::render_language_server_menu_item(
|
||||
|
@ -672,7 +672,7 @@ impl LspLogToolbarItemView {
|
|||
cx: &mut ViewContext<Self>,
|
||||
) -> impl Element<Self> {
|
||||
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
|
||||
.and_then(|row| {
|
||||
let worktree = row.worktree.read(cx);
|
||||
|
@ -728,7 +728,7 @@ impl LspLogToolbarItemView {
|
|||
.with_height(theme.toolbar_dropdown_menu.row_height)
|
||||
})
|
||||
.with_child(
|
||||
MouseEventHandler::<ActivateLog, _>::new(id.0, cx, move |state, _| {
|
||||
MouseEventHandler::new::<ActivateLog, _>(id.0, cx, move |state, _| {
|
||||
let style = theme
|
||||
.toolbar_dropdown_menu
|
||||
.item
|
||||
|
@ -746,7 +746,7 @@ impl LspLogToolbarItemView {
|
|||
}),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<ActivateRpcTrace, _>::new(id.0, cx, move |state, cx| {
|
||||
MouseEventHandler::new::<ActivateRpcTrace, _>(id.0, cx, move |state, cx| {
|
||||
let style = theme
|
||||
.toolbar_dropdown_menu
|
||||
.item
|
||||
|
|
|
@ -389,7 +389,7 @@ impl View for SyntaxTreeView {
|
|||
{
|
||||
let layer = layer.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();
|
||||
UniformList::new(
|
||||
self.list_state.clone(),
|
||||
|
@ -505,7 +505,7 @@ impl SyntaxTreeToolbarItemView {
|
|||
.with_child(Self::render_header(&theme, &active_layer, cx))
|
||||
.with_children(self.menu_open.then(|| {
|
||||
Overlay::new(
|
||||
MouseEventHandler::<Menu, _>::new(0, cx, move |_, cx| {
|
||||
MouseEventHandler::new::<Menu, _>(0, cx, move |_, cx| {
|
||||
Flex::column()
|
||||
.with_children(active_buffer.syntax_layers().enumerate().map(
|
||||
|(ix, layer)| {
|
||||
|
@ -564,7 +564,7 @@ impl SyntaxTreeToolbarItemView {
|
|||
cx: &mut ViewContext<Self>,
|
||||
) -> impl Element<Self> {
|
||||
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);
|
||||
Flex::row()
|
||||
.with_child(
|
||||
|
@ -596,7 +596,7 @@ impl SyntaxTreeToolbarItemView {
|
|||
cx: &mut ViewContext<Self>,
|
||||
) -> impl Element<Self> {
|
||||
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 style = theme
|
||||
.toolbar_dropdown_menu
|
||||
|
|
|
@ -112,7 +112,7 @@ impl<D: PickerDelegate> View for Picker<D> {
|
|||
let selected_ix = this.delegate.selected_index();
|
||||
range.end = cmp::min(range.end, this.delegate.match_count());
|
||||
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)
|
||||
})
|
||||
// Capture mouse events
|
||||
|
|
|
@ -1407,7 +1407,7 @@ impl ProjectPanel {
|
|||
|
||||
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
|
||||
.in_state(details.is_selected)
|
||||
.style_for(state)
|
||||
|
@ -1519,7 +1519,7 @@ impl View for ProjectPanel {
|
|||
if has_worktree {
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<ProjectPanel, _>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::new::<ProjectPanel, _>(0, cx, |_, cx| {
|
||||
UniformList::new(
|
||||
self.list.clone(),
|
||||
self.visible_entries
|
||||
|
@ -1563,7 +1563,7 @@ impl View for ProjectPanel {
|
|||
} else {
|
||||
Flex::column()
|
||||
.with_child(
|
||||
MouseEventHandler::<Self, _>::new(2, cx, {
|
||||
MouseEventHandler::new::<Self, _>(2, cx, {
|
||||
let button_style = theme.open_project_button.clone();
|
||||
let context_menu_item_style = theme::current(cx).context_menu.item.clone();
|
||||
move |state, cx| {
|
||||
|
|
|
@ -416,7 +416,7 @@ impl BufferSearchBar {
|
|||
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||
let is_active = self.search_options.contains(option);
|
||||
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 style = theme
|
||||
.search
|
||||
|
@ -463,7 +463,7 @@ impl BufferSearchBar {
|
|||
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||
|
||||
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 style = theme.search.option_button.inactive_state().style_for(state);
|
||||
Label::new(icon, style.text.clone())
|
||||
|
@ -497,7 +497,7 @@ impl BufferSearchBar {
|
|||
let action_type_id = 0_usize;
|
||||
|
||||
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 style = theme.search.action_button.style_for(state);
|
||||
Label::new(icon, style.text.clone())
|
||||
|
@ -527,7 +527,7 @@ impl BufferSearchBar {
|
|||
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||
|
||||
enum CloseButton {}
|
||||
MouseEventHandler::<CloseButton, _>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<CloseButton, _>(0, cx, |state, _| {
|
||||
let style = theme.dismiss_button.style_for(state);
|
||||
Svg::new("icons/x_mark_8.svg")
|
||||
.with_color(style.color)
|
||||
|
|
|
@ -328,7 +328,7 @@ impl View for ProjectSearchView {
|
|||
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())
|
||||
.aligned()
|
||||
.contained()
|
||||
|
@ -1103,7 +1103,7 @@ impl ProjectSearchBar {
|
|||
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||
|
||||
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 style = theme.search.option_button.inactive_state().style_for(state);
|
||||
Label::new(icon, style.text.clone())
|
||||
|
@ -1134,7 +1134,7 @@ impl ProjectSearchBar {
|
|||
) -> AnyElement<Self> {
|
||||
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||
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 style = theme
|
||||
.search
|
||||
|
@ -1170,7 +1170,7 @@ impl ProjectSearchBar {
|
|||
|
||||
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 style = theme
|
||||
.search
|
||||
|
|
|
@ -34,7 +34,7 @@ pub fn checkbox<Tag, V, F>(
|
|||
id: usize,
|
||||
cx: &mut ViewContext<V>,
|
||||
change: F,
|
||||
) -> MouseEventHandler<Tag, V>
|
||||
) -> MouseEventHandler<V>
|
||||
where
|
||||
Tag: 'static,
|
||||
V: View,
|
||||
|
@ -43,7 +43,7 @@ where
|
|||
let label = Label::new(label, style.label.text.clone())
|
||||
.contained()
|
||||
.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>(
|
||||
|
@ -53,14 +53,14 @@ pub fn checkbox_with_label<Tag, D, V, F>(
|
|||
id: usize,
|
||||
cx: &mut ViewContext<V>,
|
||||
change: F,
|
||||
) -> MouseEventHandler<Tag, V>
|
||||
) -> MouseEventHandler<V>
|
||||
where
|
||||
Tag: 'static,
|
||||
D: Element<V>,
|
||||
V: View,
|
||||
F: 'static + Fn(&mut V, bool, &mut EventContext<V>),
|
||||
{
|
||||
MouseEventHandler::new(id, cx, |state, _| {
|
||||
MouseEventHandler::new::<Tag, _>(id, cx, |state, _| {
|
||||
let indicator = if checked {
|
||||
svg(&style.icon)
|
||||
} else {
|
||||
|
@ -143,14 +143,14 @@ pub fn cta_button<Tag, L, V, F>(
|
|||
style: &ButtonStyle,
|
||||
cx: &mut ViewContext<V>,
|
||||
f: F,
|
||||
) -> MouseEventHandler<Tag, V>
|
||||
) -> MouseEventHandler<V>
|
||||
where
|
||||
Tag: 'static,
|
||||
L: Into<Cow<'static, str>>,
|
||||
V: View,
|
||||
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);
|
||||
Label::new(label, style.text.to_owned())
|
||||
.aligned()
|
||||
|
@ -205,7 +205,7 @@ where
|
|||
))
|
||||
.with_child(
|
||||
// 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);
|
||||
icon(style)
|
||||
})
|
||||
|
|
|
@ -295,7 +295,7 @@ impl PickerDelegate for BranchListDelegate {
|
|||
let style = theme.picker.footer.clone();
|
||||
enum BranchCreateButton {}
|
||||
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);
|
||||
Label::new("Create branch", style.label.clone())
|
||||
.contained()
|
||||
|
|
|
@ -497,9 +497,8 @@ impl View for PanelButtons {
|
|||
};
|
||||
Stack::new()
|
||||
.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 = style.style_for(state);
|
||||
Flex::row()
|
||||
.with_child(
|
||||
|
|
|
@ -290,7 +290,7 @@ pub mod simple_message_notification {
|
|||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
|
||||
let style = theme.dismiss_button.style_for(state);
|
||||
Svg::new("icons/x_mark_8.svg")
|
||||
.with_color(style.color)
|
||||
|
@ -319,7 +319,7 @@ pub mod simple_message_notification {
|
|||
.with_children({
|
||||
click_message
|
||||
.map(|click_message| {
|
||||
MouseEventHandler::<MessageNotificationTag, _>::new(
|
||||
MouseEventHandler::new::<MessageNotificationTag, _>(
|
||||
0,
|
||||
cx,
|
||||
|state, _| {
|
||||
|
|
|
@ -1211,7 +1211,7 @@ impl Pane {
|
|||
|
||||
enum Tab {}
|
||||
let mouse_event_handler =
|
||||
MouseEventHandler::<Tab, Pane>::new(ix, cx, |_, cx| {
|
||||
MouseEventHandler::new::<Tab, _>(ix, cx, |_, cx| {
|
||||
Self::render_tab(
|
||||
&item,
|
||||
pane.clone(),
|
||||
|
@ -1420,7 +1420,7 @@ impl Pane {
|
|||
let item_id = item.id();
|
||||
enum TabCloseButton {}
|
||||
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() {
|
||||
icon.with_color(tab_style.icon_close_active)
|
||||
} else {
|
||||
|
@ -1485,7 +1485,7 @@ impl Pane {
|
|||
) -> AnyElement<Pane> {
|
||||
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 style = theme.pane_button.in_state(is_active).style_for(mouse_state);
|
||||
Svg::new(icon)
|
||||
|
@ -1547,7 +1547,7 @@ impl View for Pane {
|
|||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
enum MouseNavigationHandler {}
|
||||
|
||||
MouseEventHandler::<MouseNavigationHandler, _>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::new::<MouseNavigationHandler, _>(0, cx, |_, cx| {
|
||||
let active_item_index = self.active_item_index;
|
||||
|
||||
if let Some(active_item) = self.active_item() {
|
||||
|
@ -1559,7 +1559,7 @@ impl View for Pane {
|
|||
|
||||
enum TabBarEventHandler {}
|
||||
stack.add_child(
|
||||
MouseEventHandler::<TabBarEventHandler, _>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::new::<TabBarEventHandler, _>(0, cx, |_, _| {
|
||||
Empty::new()
|
||||
.contained()
|
||||
.with_style(theme.workspace.tab_bar.container)
|
||||
|
|
|
@ -19,7 +19,7 @@ pub fn dragged_item_receiver<Tag, D, F>(
|
|||
split_margin: Option<f32>,
|
||||
cx: &mut ViewContext<Pane>,
|
||||
render_child: F,
|
||||
) -> MouseEventHandler<Tag, Pane>
|
||||
) -> MouseEventHandler<Pane>
|
||||
where
|
||||
Tag: 'static,
|
||||
D: Element<Pane>,
|
||||
|
@ -39,7 +39,7 @@ where
|
|||
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
|
||||
// of if mouse position was accessed before
|
||||
let drag_position = if state.hovered() { drag_position } else { None };
|
||||
|
|
|
@ -212,7 +212,7 @@ impl Member {
|
|||
let leader_user_id = leader.user.id;
|
||||
let app_state = Arc::downgrade(app_state);
|
||||
Some(
|
||||
MouseEventHandler::<FollowIntoExternalProject, _>::new(
|
||||
MouseEventHandler::new::<FollowIntoExternalProject, _>(
|
||||
pane.id(),
|
||||
cx,
|
||||
|_, _| {
|
||||
|
|
|
@ -72,7 +72,7 @@ impl View for SharedScreen {
|
|||
enum Focus {}
|
||||
|
||||
let frame = self.frame.clone();
|
||||
MouseEventHandler::<Focus, _>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::new::<Focus, _>(0, cx, |_, cx| {
|
||||
Canvas::new(move |scene, bounds, _, _, _| {
|
||||
if let Some(frame) = frame.clone() {
|
||||
let size = constrain_size_preserving_aspect_ratio(
|
||||
|
|
|
@ -223,7 +223,7 @@ fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>
|
|||
action_name: &'static str,
|
||||
cx: &mut ViewContext<Toolbar>,
|
||||
) -> AnyElement<Toolbar> {
|
||||
MouseEventHandler::<A, _>::new(0, cx, |state, _| {
|
||||
MouseEventHandler::new::<A, _>(0, cx, |state, _| {
|
||||
let style = if enabled {
|
||||
style.style_for(state)
|
||||
} else {
|
||||
|
|
|
@ -2560,7 +2560,7 @@ impl Workspace {
|
|||
};
|
||||
|
||||
enum TitleBar {}
|
||||
MouseEventHandler::<TitleBar, _>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::new::<TitleBar, _>(0, cx, |_, cx| {
|
||||
Stack::new()
|
||||
.with_children(
|
||||
self.titlebar_item
|
||||
|
@ -2649,7 +2649,7 @@ impl Workspace {
|
|||
if self.project.read(cx).is_read_only() {
|
||||
enum DisconnectedOverlay {}
|
||||
Some(
|
||||
MouseEventHandler::<DisconnectedOverlay, _>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::new::<DisconnectedOverlay, _>(0, cx, |_, cx| {
|
||||
let theme = &theme::current(cx);
|
||||
Label::new(
|
||||
"Your connection to the remote project has been lost.",
|
||||
|
|
Loading…
Reference in a new issue