Don't scale context menus in editors with buffer font size (#11930)

With the changes in #11817, context menus within editors would get
scaled by the `buffer_font_size` instead of the `ui_font_size`.

This seems incorrect, as it results in context menus being sized
inconsistently depending on what context they originate from.

This PR makes it so that all context menus scale based on the
`ui_font_size`.

### Before

<img width="1474" alt="Screenshot 2024-05-16 at 2 43 19 PM"
src="https://github.com/zed-industries/zed/assets/1486634/a5be8113-ae24-44ad-a2e9-61105e1fcc9e">

### After

<img width="1095" alt="Screenshot 2024-05-16 at 2 43 01 PM"
src="https://github.com/zed-industries/zed/assets/1486634/3a8d51cf-fc91-4743-8f44-78344028e447">

Release Notes:

- Changed context menus in editors to no longer scale with
`buffer_font_size`.
This commit is contained in:
Marshall Bowers 2024-05-16 15:05:00 -04:00 committed by GitHub
parent 53815af2d2
commit 6513886867
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,13 +1,15 @@
use crate::{
h_flex, prelude::*, v_flex, Icon, IconName, KeyBinding, Label, List, ListItem, ListSeparator,
ListSubHeader,
ListSubHeader, WithRemSize,
};
use gpui::{
px, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
IntoElement, Render, Subscription, View, VisualContext,
};
use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev};
use settings::Settings;
use std::{rc::Rc, time::Duration};
use theme::ThemeSettings;
enum ContextMenuItem {
Separator,
@ -264,126 +266,134 @@ impl ContextMenuItem {
impl Render for ContextMenu {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
div().occlude().elevation_2(cx).flex().flex_row().child(
v_flex()
.min_w(px(200.))
.track_focus(&self.focus_handle)
.on_mouse_down_out(cx.listener(|this, _, cx| this.cancel(&menu::Cancel, cx)))
.key_context("menu")
.on_action(cx.listener(ContextMenu::select_first))
.on_action(cx.listener(ContextMenu::handle_select_last))
.on_action(cx.listener(ContextMenu::select_next))
.on_action(cx.listener(ContextMenu::select_prev))
.on_action(cx.listener(ContextMenu::confirm))
.on_action(cx.listener(ContextMenu::cancel))
.when(!self.delayed, |mut el| {
for item in self.items.iter() {
if let ContextMenuItem::Entry {
action: Some(action),
..
} = item
{
el = el.on_boxed_action(
&**action,
cx.listener(ContextMenu::on_action_dispatch),
);
WithRemSize::new(ui_font_size).child(
v_flex()
.min_w(px(200.))
.track_focus(&self.focus_handle)
.on_mouse_down_out(cx.listener(|this, _, cx| this.cancel(&menu::Cancel, cx)))
.key_context("menu")
.on_action(cx.listener(ContextMenu::select_first))
.on_action(cx.listener(ContextMenu::handle_select_last))
.on_action(cx.listener(ContextMenu::select_next))
.on_action(cx.listener(ContextMenu::select_prev))
.on_action(cx.listener(ContextMenu::confirm))
.on_action(cx.listener(ContextMenu::cancel))
.when(!self.delayed, |mut el| {
for item in self.items.iter() {
if let ContextMenuItem::Entry {
action: Some(action),
..
} = item
{
el = el.on_boxed_action(
&**action,
cx.listener(ContextMenu::on_action_dispatch),
);
}
}
}
el
})
.flex_none()
.child(List::new().children(self.items.iter_mut().enumerate().map(
|(ix, item)| {
match item {
ContextMenuItem::Separator => ListSeparator.into_any_element(),
ContextMenuItem::Header(header) => ListSubHeader::new(header.clone())
.inset(true)
.into_any_element(),
ContextMenuItem::Entry {
toggled,
label,
handler,
icon,
action,
} => {
let handler = handler.clone();
let menu = cx.view().downgrade();
let label_element = if let Some(icon) = icon {
h_flex()
.gap_1()
.child(Label::new(label.clone()))
.child(Icon::new(*icon))
el
})
.flex_none()
.child(List::new().children(self.items.iter_mut().enumerate().map(
|(ix, item)| {
match item {
ContextMenuItem::Separator => ListSeparator.into_any_element(),
ContextMenuItem::Header(header) => {
ListSubHeader::new(header.clone())
.inset(true)
.into_any_element()
} else {
Label::new(label.clone()).into_any_element()
};
}
ContextMenuItem::Entry {
toggled,
label,
handler,
icon,
action,
} => {
let handler = handler.clone();
let menu = cx.view().downgrade();
ListItem::new(ix)
.inset(true)
.selected(Some(ix) == self.selected_index)
.when_some(*toggled, |list_item, toggled| {
list_item.start_slot(if toggled {
v_flex().flex_none().child(
Icon::new(IconName::Check).color(Color::Accent),
)
} else {
v_flex().flex_none().size(IconSize::default().rems())
})
})
.child(
let label_element = if let Some(icon) = icon {
h_flex()
.w_full()
.justify_between()
.child(label_element)
.debug_selector(|| format!("MENU_ITEM-{}", label))
.children(action.as_ref().and_then(|action| {
self.action_context
.as_ref()
.map(|focus| {
KeyBinding::for_action_in(
&**action, focus, cx,
)
})
.unwrap_or_else(|| {
KeyBinding::for_action(&**action, cx)
})
.map(|binding| div().ml_1().child(binding))
})),
)
.on_click(move |_, cx| {
handler(cx);
menu.update(cx, |menu, cx| {
menu.clicked = true;
cx.emit(DismissEvent);
.gap_1()
.child(Label::new(label.clone()))
.child(Icon::new(*icon))
.into_any_element()
} else {
Label::new(label.clone()).into_any_element()
};
ListItem::new(ix)
.inset(true)
.selected(Some(ix) == self.selected_index)
.when_some(*toggled, |list_item, toggled| {
list_item.start_slot(if toggled {
v_flex().flex_none().child(
Icon::new(IconName::Check).color(Color::Accent),
)
} else {
v_flex()
.flex_none()
.size(IconSize::default().rems())
})
})
.ok();
})
.into_any_element()
}
ContextMenuItem::CustomEntry {
entry_render,
handler,
} => {
let handler = handler.clone();
let menu = cx.view().downgrade();
ListItem::new(ix)
.inset(true)
.selected(Some(ix) == self.selected_index)
.on_click(move |_, cx| {
handler(cx);
menu.update(cx, |menu, cx| {
menu.clicked = true;
cx.emit(DismissEvent);
.child(
h_flex()
.w_full()
.justify_between()
.child(label_element)
.debug_selector(|| format!("MENU_ITEM-{}", label))
.children(action.as_ref().and_then(|action| {
self.action_context
.as_ref()
.map(|focus| {
KeyBinding::for_action_in(
&**action, focus, cx,
)
})
.unwrap_or_else(|| {
KeyBinding::for_action(&**action, cx)
})
.map(|binding| div().ml_1().child(binding))
})),
)
.on_click(move |_, cx| {
handler(cx);
menu.update(cx, |menu, cx| {
menu.clicked = true;
cx.emit(DismissEvent);
})
.ok();
})
.ok();
})
.child(entry_render(cx))
.into_any_element()
.into_any_element()
}
ContextMenuItem::CustomEntry {
entry_render,
handler,
} => {
let handler = handler.clone();
let menu = cx.view().downgrade();
ListItem::new(ix)
.inset(true)
.selected(Some(ix) == self.selected_index)
.on_click(move |_, cx| {
handler(cx);
menu.update(cx, |menu, cx| {
menu.clicked = true;
cx.emit(DismissEvent);
})
.ok();
})
.child(entry_render(cx))
.into_any_element()
}
}
}
},
))),
},
))),
),
)
}
}