merged previous stuffs on master

This commit is contained in:
2026-02-20 19:48:03 +07:00
parent 014757cfc9
commit b88955e62c
176 changed files with 11152 additions and 11212 deletions

View File

@@ -1,16 +1,17 @@
use gpui::prelude::FluentBuilder;
use gpui::{
anchored, deferred, div, px, App, AppContext as _, ClickEvent, Context, DismissEvent, Entity,
Focusable, InteractiveElement as _, IntoElement, KeyBinding, OwnedMenu, ParentElement, Render,
SharedString, StatefulInteractiveElement, Styled, Subscription, Window,
Focusable, InteractiveElement as _, IntoElement, KeyBinding, MouseButton, OwnedMenu,
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Window,
};
use crate::actions::{Cancel, SelectLeft, SelectRight};
use crate::button::{Button, ButtonVariants};
use crate::popup_menu::PopupMenu;
use crate::menu::PopupMenu;
use crate::{h_flex, Selectable, Sizable};
const CONTEXT: &str = "AppMenuBar";
pub fn init(cx: &mut App) {
cx.bind_keys([
KeyBinding::new("escape", Cancel, Some(CONTEXT)),
@@ -22,67 +23,74 @@ pub fn init(cx: &mut App) {
/// The application menu bar, for Windows and Linux.
pub struct AppMenuBar {
menus: Vec<Entity<AppMenu>>,
selected_ix: Option<usize>,
selected_index: Option<usize>,
}
impl AppMenuBar {
/// Create a new app menu bar.
pub fn new(window: &mut Window, cx: &mut App) -> Entity<Self> {
pub fn new(cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
let menu_bar = cx.entity();
let menus = cx
.get_menus()
.unwrap_or_default()
.iter()
.enumerate()
.map(|(ix, menu)| AppMenu::new(ix, menu, menu_bar.clone(), window, cx))
.collect();
Self {
selected_ix: None,
menus,
}
let mut this = Self {
selected_index: None,
menus: Vec::new(),
};
this.reload(cx);
this
})
}
fn move_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
let Some(selected_ix) = self.selected_ix else {
/// Reload the menus from the app.
pub fn reload(&mut self, cx: &mut Context<Self>) {
let menu_bar = cx.entity();
self.menus = cx
.get_menus()
.unwrap_or_default()
.iter()
.enumerate()
.map(|(ix, menu)| AppMenu::new(ix, menu, menu_bar.clone(), cx))
.collect();
self.selected_index = None;
cx.notify();
}
fn on_move_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
let Some(selected_index) = self.selected_index else {
return;
};
let new_ix = if selected_ix == 0 {
let new_ix = if selected_index == 0 {
self.menus.len().saturating_sub(1)
} else {
selected_ix.saturating_sub(1)
selected_index.saturating_sub(1)
};
self.set_selected_ix(Some(new_ix), window, cx);
self.set_selected_index(Some(new_ix), window, cx);
}
fn move_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
let Some(selected_ix) = self.selected_ix else {
fn on_move_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
let Some(selected_index) = self.selected_index else {
return;
};
let new_ix = if selected_ix + 1 >= self.menus.len() {
let new_ix = if selected_index + 1 >= self.menus.len() {
0
} else {
selected_ix + 1
selected_index + 1
};
self.set_selected_ix(Some(new_ix), window, cx);
self.set_selected_index(Some(new_ix), window, cx);
}
fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
self.set_selected_ix(None, window, cx);
fn on_cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
self.set_selected_index(None, window, cx);
}
fn set_selected_ix(&mut self, ix: Option<usize>, _: &mut Window, cx: &mut Context<Self>) {
self.selected_ix = ix;
fn set_selected_index(&mut self, ix: Option<usize>, _: &mut Window, cx: &mut Context<Self>) {
self.selected_index = ix;
cx.notify();
}
#[inline]
fn has_activated_menu(&self) -> bool {
self.selected_ix.is_some()
self.selected_index.is_some()
}
}
@@ -91,9 +99,9 @@ impl Render for AppMenuBar {
h_flex()
.id("app-menu-bar")
.key_context(CONTEXT)
.on_action(cx.listener(Self::move_left))
.on_action(cx.listener(Self::move_right))
.on_action(cx.listener(Self::cancel))
.on_action(cx.listener(Self::on_move_left))
.on_action(cx.listener(Self::on_move_right))
.on_action(cx.listener(Self::on_cancel))
.size_full()
.gap_x_1()
.overflow_x_scroll()
@@ -117,7 +125,6 @@ impl AppMenu {
ix: usize,
menu: &OwnedMenu,
menu_bar: Entity<AppMenuBar>,
_: &mut Window,
cx: &mut App,
) -> Entity<Self> {
let name = menu.name.clone();
@@ -173,7 +180,7 @@ impl AppMenu {
self._subscription.take();
self.popup_menu.take();
self.menu_bar.update(cx, |state, cx| {
state.cancel(&Cancel, window, cx);
state.on_cancel(&Cancel, window, cx);
});
}
@@ -183,11 +190,11 @@ impl AppMenu {
window: &mut Window,
cx: &mut Context<Self>,
) {
let is_selected = self.menu_bar.read(cx).selected_ix == Some(self.ix);
let is_selected = self.menu_bar.read(cx).selected_index == Some(self.ix);
self.menu_bar.update(cx, |state, cx| {
let new_ix = if is_selected { None } else { Some(self.ix) };
state.set_selected_ix(new_ix, window, cx);
state.set_selected_index(new_ix, window, cx);
});
}
@@ -202,7 +209,7 @@ impl AppMenu {
}
self.menu_bar.update(cx, |state, cx| {
state.set_selected_ix(Some(self.ix), window, cx);
state.set_selected_index(Some(self.ix), window, cx);
});
}
}
@@ -210,7 +217,7 @@ impl AppMenu {
impl Render for AppMenu {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let menu_bar = self.menu_bar.read(cx);
let is_selected = menu_bar.selected_ix == Some(self.ix);
let is_selected = menu_bar.selected_index == Some(self.ix);
div()
.id(self.ix)
@@ -219,10 +226,15 @@ impl Render for AppMenu {
Button::new("menu")
.small()
.py_0p5()
.xsmall()
.compact()
.ghost()
.label(self.name.clone())
.selected(is_selected)
.on_mouse_down(MouseButton::Left, |_, window, cx| {
// Stop propagation to avoid dragging the window.
window.prevent_default();
cx.stop_propagation();
})
.on_click(cx.listener(Self::handle_trigger_click)),
)
.on_hover(cx.listener(Self::handle_hover))