crates/ui/src/components/context_menu.rs 🔗
@@ -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();
+ })
+ .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();
})
- .ok();
- })
- .child(entry_render(cx))
- .into_any_element()
+ .child(entry_render(cx))
+ .into_any_element()
+ }
}
- }
- },
- ))),
+ },
+ ))),
+ ),
)
}
}