Eliminate GPUI View, ViewContext, and WindowContext types (#22632)
There's still a bit more work to do on this, but this PR is compiling (with warnings) after eliminating the key types. When the tasks below are complete, this will be the new narrative for GPUI: - `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit of state, and if `T` implements `Render`, then `Entity<T>` implements `Element`. - `&mut App` This replaces `AppContext` and represents the app. - `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It is provided by the framework when updating an entity. - `&mut Window` Broken out of `&mut WindowContext` which no longer exists. Every method that once took `&mut WindowContext` now takes `&mut Window, &mut App` and every method that took `&mut ViewContext<T>` now takes `&mut Window, &mut Context<T>` Not pictured here are the two other failed attempts. It's been quite a month! Tasks: - [x] Remove `View`, `ViewContext`, `WindowContext` and thread through `Window` - [x] [@cole-miller @mikayla-maki] Redraw window when entities change - [x] [@cole-miller @mikayla-maki] Get examples and Zed running - [x] [@cole-miller @mikayla-maki] Fix Zed rendering - [x] [@mikayla-maki] Fix todo! macros and comments - [x] Fix a bug where the editor would not be redrawn because of view caching - [x] remove publicness window.notify() and replace with `AppContext::notify` - [x] remove `observe_new_window_models`, replace with `observe_new_models` with an optional window - [x] Fix a bug where the project panel would not be redrawn because of the wrong refresh() call being used - [x] Fix the tests - [x] Fix warnings by eliminating `Window` params or using `_` - [x] Fix conflicts - [x] Simplify generic code where possible - [x] Rename types - [ ] Update docs ### issues post merge - [x] Issues switching between normal and insert mode - [x] Assistant re-rendering failure - [x] Vim test failures - [x] Mac build issue Release Notes: - N/A --------- Co-authored-by: Antonio Scandurra <me@as-cii.com> Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Joseph <joseph@zed.dev> Co-authored-by: max <max@zed.dev> Co-authored-by: Michael Sloan <michael@zed.dev> Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local> Co-authored-by: Mikayla <mikayla.c.maki@gmail.com> Co-authored-by: joão <joao@zed.dev>
This commit is contained in:
parent
21b4a0d50e
commit
6fca1d2b0b
648 changed files with 36248 additions and 28208 deletions
|
@ -71,7 +71,7 @@ impl Avatar {
|
|||
}
|
||||
|
||||
impl RenderOnce for Avatar {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let border_width = if self.border_color.is_some() {
|
||||
px(2.)
|
||||
} else {
|
||||
|
@ -79,7 +79,7 @@ impl RenderOnce for Avatar {
|
|||
};
|
||||
|
||||
let image_size = self.size.unwrap_or_else(|| rems(1.).into());
|
||||
let container_size = image_size.to_pixels(cx.rem_size()) + border_width * 2.;
|
||||
let container_size = image_size.to_pixels(window.rem_size()) + border_width * 2.;
|
||||
|
||||
div()
|
||||
.size(container_size)
|
||||
|
|
|
@ -16,7 +16,7 @@ pub enum AudioStatus {
|
|||
#[derive(IntoElement)]
|
||||
pub struct AvatarAudioStatusIndicator {
|
||||
audio_status: AudioStatus,
|
||||
tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
|
||||
tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||
}
|
||||
|
||||
impl AvatarAudioStatusIndicator {
|
||||
|
@ -29,17 +29,17 @@ impl AvatarAudioStatusIndicator {
|
|||
}
|
||||
|
||||
/// Sets the tooltip for the indicator.
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.tooltip = Some(Box::new(tooltip));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for AvatarAudioStatusIndicator {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let icon_size = IconSize::Indicator;
|
||||
|
||||
let width_in_px = icon_size.rems() * cx.rem_size();
|
||||
let width_in_px = icon_size.rems() * window.rem_size();
|
||||
let padding_x = px(4.);
|
||||
|
||||
div()
|
||||
|
@ -65,7 +65,7 @@ impl RenderOnce for AvatarAudioStatusIndicator {
|
|||
.color(Color::Error),
|
||||
)
|
||||
.when_some(self.tooltip, |this, tooltip| {
|
||||
this.tooltip(move |cx| tooltip(cx))
|
||||
this.tooltip(move |window, cx| tooltip(window, cx))
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ impl AvatarAvailabilityIndicator {
|
|||
}
|
||||
|
||||
impl RenderOnce for AvatarAvailabilityIndicator {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let avatar_size = self.avatar_size.unwrap_or_else(|| cx.rem_size());
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let avatar_size = self.avatar_size.unwrap_or_else(|| window.rem_size());
|
||||
|
||||
// HACK: non-integer sizes result in oval indicators.
|
||||
let indicator_size = (avatar_size * 0.4).round();
|
||||
|
|
|
@ -271,7 +271,7 @@ impl Clickable for Button {
|
|||
/// Sets the click event handler for the button.
|
||||
fn on_click(
|
||||
mut self,
|
||||
handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
|
||||
handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.base = self.base.on_click(handler);
|
||||
self
|
||||
|
@ -359,16 +359,14 @@ impl ButtonCommon for Button {
|
|||
/// use ui::Tooltip;
|
||||
///
|
||||
/// Button::new("button_id", "Click me!")
|
||||
/// .tooltip(move |cx| {
|
||||
/// Tooltip::text("This is a tooltip", cx)
|
||||
/// })
|
||||
/// .tooltip(Tooltip::text_f("This is a tooltip", cx))
|
||||
/// .on_click(|event, cx| {
|
||||
/// // Handle click event
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// This will create a button with a tooltip that displays "This is a tooltip" when hovered over.
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.base = self.base.tooltip(tooltip);
|
||||
self
|
||||
}
|
||||
|
@ -381,7 +379,7 @@ impl ButtonCommon for Button {
|
|||
|
||||
impl RenderOnce for Button {
|
||||
#[allow(refining_impl_trait)]
|
||||
fn render(self, cx: &mut WindowContext) -> ButtonLike {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> ButtonLike {
|
||||
let is_disabled = self.base.disabled;
|
||||
let is_selected = self.base.selected;
|
||||
|
||||
|
@ -445,7 +443,7 @@ impl ComponentPreview for Button {
|
|||
"A button allows users to take actions, and make choices, with a single tap."
|
||||
}
|
||||
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group_with_title(
|
||||
"Styles",
|
||||
|
|
|
@ -80,7 +80,7 @@ impl SelectableButton for ButtonIcon {
|
|||
}
|
||||
|
||||
impl RenderOnce for ButtonIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
let icon = self
|
||||
.selected_icon
|
||||
.filter(|_| self.selected)
|
||||
|
|
|
@ -33,7 +33,7 @@ pub trait ButtonCommon: Clickable + Disableable {
|
|||
///
|
||||
/// Nearly all interactable elements should have a tooltip. Some example
|
||||
/// exceptions might a scroll bar, or a slider.
|
||||
fn tooltip(self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self;
|
||||
fn tooltip(self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self;
|
||||
|
||||
fn layer(self, elevation: ElevationIndex) -> Self;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ pub enum TintColor {
|
|||
}
|
||||
|
||||
impl TintColor {
|
||||
fn button_like_style(self, cx: &mut WindowContext) -> ButtonLikeStyles {
|
||||
fn button_like_style(self, cx: &mut App) -> ButtonLikeStyles {
|
||||
match self {
|
||||
TintColor::Accent => ButtonLikeStyles {
|
||||
background: cx.theme().status().info_background,
|
||||
|
@ -146,7 +146,7 @@ pub(crate) struct ButtonLikeStyles {
|
|||
pub icon_color: Hsla,
|
||||
}
|
||||
|
||||
fn element_bg_from_elevation(elevation: Option<ElevationIndex>, cx: &mut WindowContext) -> Hsla {
|
||||
fn element_bg_from_elevation(elevation: Option<ElevationIndex>, cx: &mut App) -> Hsla {
|
||||
match elevation {
|
||||
Some(ElevationIndex::Background) => cx.theme().colors().element_background,
|
||||
Some(ElevationIndex::ElevatedSurface) => cx.theme().colors().elevated_surface_background,
|
||||
|
@ -160,7 +160,8 @@ impl ButtonStyle {
|
|||
pub(crate) fn enabled(
|
||||
self,
|
||||
elevation: Option<ElevationIndex>,
|
||||
cx: &mut WindowContext,
|
||||
|
||||
cx: &mut App,
|
||||
) -> ButtonLikeStyles {
|
||||
match self {
|
||||
ButtonStyle::Filled => ButtonLikeStyles {
|
||||
|
@ -188,7 +189,8 @@ impl ButtonStyle {
|
|||
pub(crate) fn hovered(
|
||||
self,
|
||||
elevation: Option<ElevationIndex>,
|
||||
cx: &mut WindowContext,
|
||||
|
||||
cx: &mut App,
|
||||
) -> ButtonLikeStyles {
|
||||
match self {
|
||||
ButtonStyle::Filled => {
|
||||
|
@ -225,7 +227,7 @@ impl ButtonStyle {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn active(self, cx: &mut WindowContext) -> ButtonLikeStyles {
|
||||
pub(crate) fn active(self, cx: &mut App) -> ButtonLikeStyles {
|
||||
match self {
|
||||
ButtonStyle::Filled => ButtonLikeStyles {
|
||||
background: cx.theme().colors().element_active,
|
||||
|
@ -252,7 +254,7 @@ impl ButtonStyle {
|
|||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn focused(self, cx: &mut WindowContext) -> ButtonLikeStyles {
|
||||
pub(crate) fn focused(self, window: &mut Window, cx: &mut App) -> ButtonLikeStyles {
|
||||
match self {
|
||||
ButtonStyle::Filled => ButtonLikeStyles {
|
||||
background: cx.theme().colors().element_background,
|
||||
|
@ -280,7 +282,8 @@ impl ButtonStyle {
|
|||
pub(crate) fn disabled(
|
||||
self,
|
||||
elevation: Option<ElevationIndex>,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> ButtonLikeStyles {
|
||||
match self {
|
||||
ButtonStyle::Filled => ButtonLikeStyles {
|
||||
|
@ -347,9 +350,9 @@ pub struct ButtonLike {
|
|||
pub(super) layer: Option<ElevationIndex>,
|
||||
size: ButtonSize,
|
||||
rounding: Option<ButtonLikeRounding>,
|
||||
tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
|
||||
tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||
cursor_style: CursorStyle,
|
||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
children: SmallVec<[AnyElement; 2]>,
|
||||
}
|
||||
|
||||
|
@ -415,7 +418,7 @@ impl SelectableButton for ButtonLike {
|
|||
}
|
||||
|
||||
impl Clickable for ButtonLike {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_click = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
|
@ -453,7 +456,7 @@ impl ButtonCommon for ButtonLike {
|
|||
self
|
||||
}
|
||||
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.tooltip = Some(Box::new(tooltip));
|
||||
self
|
||||
}
|
||||
|
@ -478,7 +481,7 @@ impl ParentElement for ButtonLike {
|
|||
}
|
||||
|
||||
impl RenderOnce for ButtonLike {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let style = self
|
||||
.selected_style
|
||||
.filter(|_| self.selected)
|
||||
|
@ -515,15 +518,15 @@ impl RenderOnce for ButtonLike {
|
|||
.when_some(
|
||||
self.on_click.filter(|_| !self.disabled),
|
||||
|this, on_click| {
|
||||
this.on_mouse_down(MouseButton::Left, |_, cx| cx.prevent_default())
|
||||
.on_click(move |event, cx| {
|
||||
this.on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
|
||||
.on_click(move |event, window, cx| {
|
||||
cx.stop_propagation();
|
||||
(on_click)(event, cx)
|
||||
(on_click)(event, window, cx)
|
||||
})
|
||||
},
|
||||
)
|
||||
.when_some(self.tooltip, |this, tooltip| {
|
||||
this.tooltip(move |cx| tooltip(cx))
|
||||
this.tooltip(move |window, cx| tooltip(window, cx))
|
||||
})
|
||||
.children(self.children)
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ impl SelectableButton for IconButton {
|
|||
impl Clickable for IconButton {
|
||||
fn on_click(
|
||||
mut self,
|
||||
handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
|
||||
handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.base = self.base.on_click(handler);
|
||||
self
|
||||
|
@ -129,7 +129,7 @@ impl ButtonCommon for IconButton {
|
|||
self
|
||||
}
|
||||
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.base = self.base.tooltip(tooltip);
|
||||
self
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ impl VisibleOnHover for IconButton {
|
|||
}
|
||||
|
||||
impl RenderOnce for IconButton {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let is_disabled = self.base.disabled;
|
||||
let is_selected = self.base.selected;
|
||||
let selected_style = self.base.selected_style;
|
||||
|
@ -157,7 +157,7 @@ impl RenderOnce for IconButton {
|
|||
self.base
|
||||
.map(|this| match self.shape {
|
||||
IconButtonShape::Square => {
|
||||
let size = self.icon_size.square(cx);
|
||||
let size = self.icon_size.square(window, cx);
|
||||
this.width(size.into()).height(size.into())
|
||||
}
|
||||
IconButtonShape::Wide => this,
|
||||
|
|
|
@ -79,7 +79,7 @@ impl Disableable for ToggleButton {
|
|||
}
|
||||
|
||||
impl Clickable for ToggleButton {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.base = self.base.on_click(handler);
|
||||
self
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ impl ButtonCommon for ToggleButton {
|
|||
self
|
||||
}
|
||||
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
|
||||
fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.base = self.base.tooltip(tooltip);
|
||||
self
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ impl ButtonCommon for ToggleButton {
|
|||
}
|
||||
|
||||
impl RenderOnce for ToggleButton {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
let is_disabled = self.base.disabled;
|
||||
let is_selected = self.base.selected;
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ impl Styled for ContentGroup {
|
|||
}
|
||||
|
||||
impl RenderOnce for ContentGroup {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
// TODO:
|
||||
// Baked in padding will make scrollable views inside of content boxes awkward.
|
||||
//
|
||||
|
@ -95,7 +95,7 @@ impl ComponentPreview for ContentGroup {
|
|||
ExampleLabelSide::Bottom
|
||||
}
|
||||
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![example_group(vec![
|
||||
single_example(
|
||||
"Default",
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::{
|
|||
List, ListItem, ListSeparator, ListSubHeader,
|
||||
};
|
||||
use gpui::{
|
||||
px, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
|
||||
IntoElement, Render, Subscription, View, VisualContext,
|
||||
px, Action, AnyElement, App, AppContext as _, DismissEvent, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, IntoElement, Render, Subscription,
|
||||
};
|
||||
use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev};
|
||||
use settings::Settings;
|
||||
|
@ -18,20 +18,20 @@ pub enum ContextMenuItem {
|
|||
Label(SharedString),
|
||||
Entry(ContextMenuEntry),
|
||||
CustomEntry {
|
||||
entry_render: Box<dyn Fn(&mut WindowContext) -> AnyElement>,
|
||||
handler: Rc<dyn Fn(Option<&FocusHandle>, &mut WindowContext)>,
|
||||
entry_render: Box<dyn Fn(&mut Window, &mut App) -> AnyElement>,
|
||||
handler: Rc<dyn Fn(Option<&FocusHandle>, &mut Window, &mut App)>,
|
||||
selectable: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl ContextMenuItem {
|
||||
pub fn custom_entry(
|
||||
entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static,
|
||||
handler: impl Fn(&mut WindowContext) + 'static,
|
||||
entry_render: impl Fn(&mut Window, &mut App) -> AnyElement + 'static,
|
||||
handler: impl Fn(&mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self::CustomEntry {
|
||||
entry_render: Box::new(entry_render),
|
||||
handler: Rc::new(move |_, cx| handler(cx)),
|
||||
handler: Rc::new(move |_, window, cx| handler(window, cx)),
|
||||
selectable: true,
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ pub struct ContextMenuEntry {
|
|||
icon_position: IconPosition,
|
||||
icon_size: IconSize,
|
||||
icon_color: Option<Color>,
|
||||
handler: Rc<dyn Fn(Option<&FocusHandle>, &mut WindowContext)>,
|
||||
handler: Rc<dyn Fn(Option<&FocusHandle>, &mut Window, &mut App)>,
|
||||
action: Option<Box<dyn Action>>,
|
||||
disabled: bool,
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ impl ContextMenuEntry {
|
|||
icon_position: IconPosition::Start,
|
||||
icon_size: IconSize::Small,
|
||||
icon_color: None,
|
||||
handler: Rc::new(|_, _| {}),
|
||||
handler: Rc::new(|_, _, _| {}),
|
||||
action: None,
|
||||
disabled: false,
|
||||
}
|
||||
|
@ -94,8 +94,8 @@ impl ContextMenuEntry {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn handler(mut self, handler: impl Fn(&mut WindowContext) + 'static) -> Self {
|
||||
self.handler = Rc::new(move |_, cx| handler(cx));
|
||||
pub fn handler(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self {
|
||||
self.handler = Rc::new(move |_, window, cx| handler(window, cx));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -122,8 +122,8 @@ pub struct ContextMenu {
|
|||
keep_open_on_confirm: bool,
|
||||
}
|
||||
|
||||
impl FocusableView for ContextMenu {
|
||||
fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
|
||||
impl Focusable for ContextMenu {
|
||||
fn focus_handle(&self, _cx: &App) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
@ -134,15 +134,18 @@ impl FluentBuilder for ContextMenu {}
|
|||
|
||||
impl ContextMenu {
|
||||
pub fn build(
|
||||
cx: &mut WindowContext,
|
||||
f: impl FnOnce(Self, &mut ViewContext<Self>) -> Self,
|
||||
) -> View<Self> {
|
||||
cx.new_view(|cx| {
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
f: impl FnOnce(Self, &mut Window, &mut Context<Self>) -> Self,
|
||||
) -> Entity<Self> {
|
||||
cx.new(|cx| {
|
||||
let focus_handle = cx.focus_handle();
|
||||
let _on_blur_subscription = cx.on_blur(&focus_handle, |this: &mut ContextMenu, cx| {
|
||||
this.cancel(&menu::Cancel, cx)
|
||||
});
|
||||
cx.refresh();
|
||||
let _on_blur_subscription = cx.on_blur(
|
||||
&focus_handle,
|
||||
window,
|
||||
|this: &mut ContextMenu, window, cx| this.cancel(&menu::Cancel, window, cx),
|
||||
);
|
||||
window.refresh();
|
||||
f(
|
||||
Self {
|
||||
items: Default::default(),
|
||||
|
@ -154,6 +157,7 @@ impl ContextMenu {
|
|||
_on_blur_subscription,
|
||||
keep_open_on_confirm: false,
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
|
@ -188,12 +192,12 @@ impl ContextMenu {
|
|||
mut self,
|
||||
label: impl Into<SharedString>,
|
||||
action: Option<Box<dyn Action>>,
|
||||
handler: impl Fn(&mut WindowContext) + 'static,
|
||||
handler: impl Fn(&mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.items.push(ContextMenuItem::Entry(ContextMenuEntry {
|
||||
toggle: None,
|
||||
label: label.into(),
|
||||
handler: Rc::new(move |_, cx| handler(cx)),
|
||||
handler: Rc::new(move |_, window, cx| handler(window, cx)),
|
||||
icon: None,
|
||||
icon_position: IconPosition::End,
|
||||
icon_size: IconSize::Small,
|
||||
|
@ -210,12 +214,12 @@ impl ContextMenu {
|
|||
toggled: bool,
|
||||
position: IconPosition,
|
||||
action: Option<Box<dyn Action>>,
|
||||
handler: impl Fn(&mut WindowContext) + 'static,
|
||||
handler: impl Fn(&mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.items.push(ContextMenuItem::Entry(ContextMenuEntry {
|
||||
toggle: Some((position, toggled)),
|
||||
label: label.into(),
|
||||
handler: Rc::new(move |_, cx| handler(cx)),
|
||||
handler: Rc::new(move |_, window, cx| handler(window, cx)),
|
||||
icon: None,
|
||||
icon_position: position,
|
||||
icon_size: IconSize::Small,
|
||||
|
@ -228,11 +232,11 @@ impl ContextMenu {
|
|||
|
||||
pub fn custom_row(
|
||||
mut self,
|
||||
entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static,
|
||||
entry_render: impl Fn(&mut Window, &mut App) -> AnyElement + 'static,
|
||||
) -> Self {
|
||||
self.items.push(ContextMenuItem::CustomEntry {
|
||||
entry_render: Box::new(entry_render),
|
||||
handler: Rc::new(|_, _| {}),
|
||||
handler: Rc::new(|_, _, _| {}),
|
||||
selectable: false,
|
||||
});
|
||||
self
|
||||
|
@ -240,12 +244,12 @@ impl ContextMenu {
|
|||
|
||||
pub fn custom_entry(
|
||||
mut self,
|
||||
entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static,
|
||||
handler: impl Fn(&mut WindowContext) + 'static,
|
||||
entry_render: impl Fn(&mut Window, &mut App) -> AnyElement + 'static,
|
||||
handler: impl Fn(&mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.items.push(ContextMenuItem::CustomEntry {
|
||||
entry_render: Box::new(entry_render),
|
||||
handler: Rc::new(move |_, cx| handler(cx)),
|
||||
handler: Rc::new(move |_, window, cx| handler(window, cx)),
|
||||
selectable: true,
|
||||
});
|
||||
self
|
||||
|
@ -261,12 +265,11 @@ impl ContextMenu {
|
|||
toggle: None,
|
||||
label: label.into(),
|
||||
action: Some(action.boxed_clone()),
|
||||
|
||||
handler: Rc::new(move |context, cx| {
|
||||
handler: Rc::new(move |context, window, cx| {
|
||||
if let Some(context) = &context {
|
||||
cx.focus(context);
|
||||
window.focus(context);
|
||||
}
|
||||
cx.dispatch_action(action.boxed_clone());
|
||||
window.dispatch_action(action.boxed_clone(), cx);
|
||||
}),
|
||||
icon: None,
|
||||
icon_position: IconPosition::End,
|
||||
|
@ -287,11 +290,11 @@ impl ContextMenu {
|
|||
label: label.into(),
|
||||
action: Some(action.boxed_clone()),
|
||||
|
||||
handler: Rc::new(move |context, cx| {
|
||||
handler: Rc::new(move |context, window, cx| {
|
||||
if let Some(context) = &context {
|
||||
cx.focus(context);
|
||||
window.focus(context);
|
||||
}
|
||||
cx.dispatch_action(action.boxed_clone());
|
||||
window.dispatch_action(action.boxed_clone(), cx);
|
||||
}),
|
||||
icon: None,
|
||||
icon_size: IconSize::Small,
|
||||
|
@ -308,7 +311,7 @@ impl ContextMenu {
|
|||
label: label.into(),
|
||||
|
||||
action: Some(action.boxed_clone()),
|
||||
handler: Rc::new(move |_, cx| cx.dispatch_action(action.boxed_clone())),
|
||||
handler: Rc::new(move |_, window, cx| window.dispatch_action(action.boxed_clone(), cx)),
|
||||
icon: Some(IconName::ArrowUpRight),
|
||||
icon_size: IconSize::XSmall,
|
||||
icon_position: IconPosition::End,
|
||||
|
@ -323,7 +326,7 @@ impl ContextMenu {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
|
||||
pub fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let context = self.action_context.as_ref();
|
||||
if let Some(
|
||||
ContextMenuItem::Entry(ContextMenuEntry {
|
||||
|
@ -334,7 +337,7 @@ impl ContextMenu {
|
|||
| ContextMenuItem::CustomEntry { handler, .. },
|
||||
) = self.selected_index.and_then(|ix| self.items.get(ix))
|
||||
{
|
||||
(handler)(context, cx)
|
||||
(handler)(context, window, cx)
|
||||
}
|
||||
|
||||
if !self.keep_open_on_confirm {
|
||||
|
@ -342,12 +345,12 @@ impl ContextMenu {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
|
||||
pub fn cancel(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
|
||||
cx.emit(DismissEvent);
|
||||
cx.emit(DismissEvent);
|
||||
}
|
||||
|
||||
fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext<Self>) {
|
||||
fn select_first(&mut self, _: &SelectFirst, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.selected_index = self.items.iter().position(|item| item.is_selectable());
|
||||
cx.notify();
|
||||
}
|
||||
|
@ -362,17 +365,17 @@ impl ContextMenu {
|
|||
None
|
||||
}
|
||||
|
||||
fn handle_select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
|
||||
fn handle_select_last(&mut self, _: &SelectLast, _: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.select_last().is_some() {
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
|
||||
fn select_next(&mut self, _: &SelectNext, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(ix) = self.selected_index {
|
||||
let next_index = ix + 1;
|
||||
if self.items.len() <= next_index {
|
||||
self.select_first(&SelectFirst, cx);
|
||||
self.select_first(&SelectFirst, window, cx);
|
||||
} else {
|
||||
for (ix, item) in self.items.iter().enumerate().skip(next_index) {
|
||||
if item.is_selectable() {
|
||||
|
@ -383,14 +386,14 @@ impl ContextMenu {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
self.select_first(&SelectFirst, cx);
|
||||
self.select_first(&SelectFirst, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
|
||||
pub fn select_prev(&mut self, _: &SelectPrev, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(ix) = self.selected_index {
|
||||
if ix == 0 {
|
||||
self.handle_select_last(&SelectLast, cx);
|
||||
self.handle_select_last(&SelectLast, window, cx);
|
||||
} else {
|
||||
for (ix, item) in self.items.iter().enumerate().take(ix).rev() {
|
||||
if item.is_selectable() {
|
||||
|
@ -401,11 +404,16 @@ impl ContextMenu {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
self.handle_select_last(&SelectLast, cx);
|
||||
self.handle_select_last(&SelectLast, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_action_dispatch(&mut self, dispatched: &dyn Action, cx: &mut ViewContext<Self>) {
|
||||
pub fn on_action_dispatch(
|
||||
&mut self,
|
||||
dispatched: &dyn Action,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if self.clicked {
|
||||
cx.propagate();
|
||||
return;
|
||||
|
@ -427,13 +435,15 @@ impl ContextMenu {
|
|||
self.delayed = true;
|
||||
cx.notify();
|
||||
let action = dispatched.boxed_clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.background_executor()
|
||||
.timer(Duration::from_millis(50))
|
||||
.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.cancel(&menu::Cancel, cx);
|
||||
cx.dispatch_action(action);
|
||||
cx.update(|window, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.cancel(&menu::Cancel, window, cx);
|
||||
window.dispatch_action(action, cx);
|
||||
})
|
||||
})
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
@ -461,7 +471,7 @@ impl ContextMenuItem {
|
|||
}
|
||||
|
||||
impl Render for ContextMenu {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
|
||||
|
||||
WithRemSize::new(ui_font_size)
|
||||
|
@ -473,11 +483,13 @@ impl Render for ContextMenu {
|
|||
v_flex()
|
||||
.id("context-menu")
|
||||
.min_w(px(200.))
|
||||
.max_h(vh(0.75, cx))
|
||||
.max_h(vh(0.75, window))
|
||||
.flex_1()
|
||||
.overflow_y_scroll()
|
||||
.track_focus(&self.focus_handle(cx))
|
||||
.on_mouse_down_out(cx.listener(|this, _, cx| this.cancel(&menu::Cancel, cx)))
|
||||
.on_mouse_down_out(
|
||||
cx.listener(|this, _, window, cx| this.cancel(&menu::Cancel, window, cx)),
|
||||
)
|
||||
.key_context("menu")
|
||||
.on_action(cx.listener(ContextMenu::select_first))
|
||||
.on_action(cx.listener(ContextMenu::handle_select_last))
|
||||
|
@ -527,7 +539,7 @@ impl Render for ContextMenu {
|
|||
disabled,
|
||||
}) => {
|
||||
let handler = handler.clone();
|
||||
let menu = cx.view().downgrade();
|
||||
let menu = cx.model().downgrade();
|
||||
let icon_color = if *disabled {
|
||||
Color::Muted
|
||||
} else {
|
||||
|
@ -595,19 +607,21 @@ impl Render for ContextMenu {
|
|||
.as_ref()
|
||||
.map(|focus| {
|
||||
KeyBinding::for_action_in(
|
||||
&**action, focus, cx,
|
||||
&**action, focus, window,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
KeyBinding::for_action(&**action, cx)
|
||||
KeyBinding::for_action(
|
||||
&**action, window,
|
||||
)
|
||||
})
|
||||
.map(|binding| div().ml_4().child(binding))
|
||||
})),
|
||||
)
|
||||
.on_click({
|
||||
let context = self.action_context.clone();
|
||||
move |_, cx| {
|
||||
handler(context.as_ref(), cx);
|
||||
move |_, window, cx| {
|
||||
handler(context.as_ref(), window, cx);
|
||||
menu.update(cx, |menu, cx| {
|
||||
menu.clicked = true;
|
||||
cx.emit(DismissEvent);
|
||||
|
@ -623,7 +637,7 @@ impl Render for ContextMenu {
|
|||
selectable,
|
||||
} => {
|
||||
let handler = handler.clone();
|
||||
let menu = cx.view().downgrade();
|
||||
let menu = cx.model().downgrade();
|
||||
let selectable = *selectable;
|
||||
ListItem::new(ix)
|
||||
.inset(true)
|
||||
|
@ -636,8 +650,8 @@ impl Render for ContextMenu {
|
|||
.when(selectable, |item| {
|
||||
item.on_click({
|
||||
let context = self.action_context.clone();
|
||||
move |_, cx| {
|
||||
handler(context.as_ref(), cx);
|
||||
move |_, window, cx| {
|
||||
handler(context.as_ref(), window, cx);
|
||||
menu.update(cx, |menu, cx| {
|
||||
menu.clicked = true;
|
||||
cx.emit(DismissEvent);
|
||||
|
@ -646,7 +660,7 @@ impl Render for ContextMenu {
|
|||
}
|
||||
})
|
||||
})
|
||||
.child(entry_render(cx))
|
||||
.child(entry_render(window, cx))
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ pub struct Disclosure {
|
|||
id: ElementId,
|
||||
is_open: bool,
|
||||
selected: bool,
|
||||
on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||
on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
cursor_style: CursorStyle,
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ impl Disclosure {
|
|||
|
||||
pub fn on_toggle(
|
||||
mut self,
|
||||
handler: impl Into<Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>>,
|
||||
handler: impl Into<Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>>,
|
||||
) -> Self {
|
||||
self.on_toggle = handler.into();
|
||||
self
|
||||
|
@ -42,7 +42,7 @@ impl Toggleable for Disclosure {
|
|||
}
|
||||
|
||||
impl Clickable for Disclosure {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_toggle = Some(Arc::new(handler));
|
||||
self
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ impl Clickable for Disclosure {
|
|||
}
|
||||
|
||||
impl RenderOnce for Disclosure {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
IconButton::new(
|
||||
self.id,
|
||||
match self.is_open {
|
||||
|
@ -67,7 +67,7 @@ impl RenderOnce for Disclosure {
|
|||
.icon_size(IconSize::Small)
|
||||
.toggle_state(self.selected)
|
||||
.when_some(self.on_toggle, move |this, on_toggle| {
|
||||
this.on_click(move |event, cx| on_toggle(event, cx))
|
||||
this.on_click(move |event, window, cx| on_toggle(event, window, cx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ pub enum DividerColor {
|
|||
}
|
||||
|
||||
impl DividerColor {
|
||||
pub fn hsla(self, cx: &WindowContext) -> Hsla {
|
||||
pub fn hsla(self, cx: &mut App) -> Hsla {
|
||||
match self {
|
||||
DividerColor::Border => cx.theme().colors().border,
|
||||
DividerColor::BorderVariant => cx.theme().colors().border_variant,
|
||||
|
@ -41,7 +41,7 @@ pub struct Divider {
|
|||
}
|
||||
|
||||
impl RenderOnce for Divider {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
match self.style {
|
||||
DividerStyle::Solid => self.render_solid(cx).into_any_element(),
|
||||
DividerStyle::Dashed => self.render_dashed(cx).into_any_element(),
|
||||
|
@ -96,7 +96,7 @@ impl Divider {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn render_solid(self, cx: &WindowContext) -> impl IntoElement {
|
||||
pub fn render_solid(self, cx: &mut App) -> impl IntoElement {
|
||||
div()
|
||||
.map(|this| match self.direction {
|
||||
DividerDirection::Horizontal => {
|
||||
|
@ -111,7 +111,7 @@ impl Divider {
|
|||
|
||||
// TODO: Use canvas or a shader here
|
||||
// This obviously is a short term approach
|
||||
pub fn render_dashed(self, cx: &WindowContext) -> impl IntoElement {
|
||||
pub fn render_dashed(self, cx: &mut App) -> impl IntoElement {
|
||||
let segment_count = 128;
|
||||
let segment_count_f = segment_count as f32;
|
||||
let segment_min_w = 6.;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(missing_docs)]
|
||||
use gpui::{ClickEvent, Corner, CursorStyle, MouseButton, View};
|
||||
use gpui::{ClickEvent, Corner, CursorStyle, Entity, MouseButton};
|
||||
|
||||
use crate::{prelude::*, ContextMenu, PopoverMenu};
|
||||
|
||||
|
@ -7,7 +7,7 @@ use crate::{prelude::*, ContextMenu, PopoverMenu};
|
|||
pub struct DropdownMenu {
|
||||
id: ElementId,
|
||||
label: SharedString,
|
||||
menu: View<ContextMenu>,
|
||||
menu: Entity<ContextMenu>,
|
||||
full_width: bool,
|
||||
disabled: bool,
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ impl DropdownMenu {
|
|||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
label: impl Into<SharedString>,
|
||||
menu: View<ContextMenu>,
|
||||
menu: Entity<ContextMenu>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
|
@ -41,10 +41,10 @@ impl Disableable for DropdownMenu {
|
|||
}
|
||||
|
||||
impl RenderOnce for DropdownMenu {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
PopoverMenu::new(self.id)
|
||||
.full_width(self.full_width)
|
||||
.menu(move |_cx| Some(self.menu.clone()))
|
||||
.menu(move |_window, _cx| Some(self.menu.clone()))
|
||||
.trigger(DropdownMenuTrigger::new(self.label).full_width(self.full_width))
|
||||
.attach(Corner::BottomLeft)
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ struct DropdownMenuTrigger {
|
|||
selected: bool,
|
||||
disabled: bool,
|
||||
cursor_style: CursorStyle,
|
||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
}
|
||||
|
||||
impl DropdownMenuTrigger {
|
||||
|
@ -93,7 +93,7 @@ impl Toggleable for DropdownMenuTrigger {
|
|||
}
|
||||
|
||||
impl Clickable for DropdownMenuTrigger {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_click = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ impl Clickable for DropdownMenuTrigger {
|
|||
}
|
||||
|
||||
impl RenderOnce for DropdownMenuTrigger {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let disabled = self.disabled;
|
||||
|
||||
h_flex()
|
||||
|
@ -147,10 +147,10 @@ impl RenderOnce for DropdownMenuTrigger {
|
|||
}),
|
||||
)
|
||||
.when_some(self.on_click.filter(|_| !disabled), |el, on_click| {
|
||||
el.on_mouse_down(MouseButton::Left, |_, cx| cx.prevent_default())
|
||||
.on_click(move |event, cx| {
|
||||
el.on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
|
||||
.on_click(move |event, window, cx| {
|
||||
cx.stop_propagation();
|
||||
(on_click)(event, cx)
|
||||
(on_click)(event, window, cx)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ impl Facepile {
|
|||
}
|
||||
|
||||
impl RenderOnce for Facepile {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
// Lay the faces out in reverse so they overlap in the desired order (left to right, front to back)
|
||||
self.base
|
||||
.flex()
|
||||
|
@ -67,7 +67,7 @@ impl ComponentPreview for Facepile {
|
|||
\n\nFacepiles are used to display a group of people or things,\
|
||||
such as a list of participants in a collaboration session."
|
||||
}
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
let few_faces: [&'static str; 3] = [
|
||||
"https://avatars.githubusercontent.com/u/1714999?s=60&v=4",
|
||||
"https://avatars.githubusercontent.com/u/67129314?s=60&v=4",
|
||||
|
|
|
@ -49,7 +49,7 @@ impl From<AnimationElement<Icon>> for AnyIcon {
|
|||
}
|
||||
|
||||
impl RenderOnce for AnyIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
match self {
|
||||
Self::Icon(icon) => icon.into_any_element(),
|
||||
Self::AnimatedIcon(animated_icon) => animated_icon.into_any_element(),
|
||||
|
@ -88,8 +88,8 @@ impl IconSize {
|
|||
/// The returned tuple contains:
|
||||
/// 1. The length of one side of the square
|
||||
/// 2. The padding of one side of the square
|
||||
pub fn square_components(&self, cx: &mut WindowContext) -> (Pixels, Pixels) {
|
||||
let icon_size = self.rems() * cx.rem_size();
|
||||
pub fn square_components(&self, window: &mut Window, cx: &mut App) -> (Pixels, Pixels) {
|
||||
let icon_size = self.rems() * window.rem_size();
|
||||
let padding = match self {
|
||||
IconSize::Indicator => DynamicSpacing::Base00.px(cx),
|
||||
IconSize::XSmall => DynamicSpacing::Base02.px(cx),
|
||||
|
@ -102,8 +102,8 @@ impl IconSize {
|
|||
}
|
||||
|
||||
/// Returns the length of a side of the square that contains this [`IconSize`], with padding.
|
||||
pub fn square(&self, cx: &mut WindowContext) -> Pixels {
|
||||
let (icon_size, padding) = self.square_components(cx);
|
||||
pub fn square(&self, window: &mut Window, cx: &mut App) -> Pixels {
|
||||
let (icon_size, padding) = self.square_components(window, cx);
|
||||
|
||||
icon_size + padding * 2.
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ impl Icon {
|
|||
}
|
||||
|
||||
impl RenderOnce for Icon {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
match self.source {
|
||||
IconSource::Svg(path) => svg()
|
||||
.with_transformation(self.transformation)
|
||||
|
@ -461,7 +461,7 @@ impl IconWithIndicator {
|
|||
}
|
||||
|
||||
impl RenderOnce for IconWithIndicator {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let indicator_border_color = self
|
||||
.indicator_border_color
|
||||
.unwrap_or_else(|| cx.theme().colors().elevated_surface_background);
|
||||
|
@ -486,7 +486,7 @@ impl RenderOnce for IconWithIndicator {
|
|||
}
|
||||
|
||||
impl ComponentPreview for Icon {
|
||||
fn examples(_cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Icon>> {
|
||||
fn examples(_window: &mut Window, _cx: &mut App) -> Vec<ComponentExampleGroup<Icon>> {
|
||||
let arrow_icons = vec![
|
||||
IconName::ArrowDown,
|
||||
IconName::ArrowLeft,
|
||||
|
|
|
@ -17,7 +17,7 @@ impl DecoratedIcon {
|
|||
}
|
||||
|
||||
impl RenderOnce for DecoratedIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
div()
|
||||
.relative()
|
||||
.size(self.icon.size)
|
||||
|
@ -27,7 +27,7 @@ impl RenderOnce for DecoratedIcon {
|
|||
}
|
||||
|
||||
impl ComponentPreview for DecoratedIcon {
|
||||
fn examples(cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut Window, cx: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
let icon_1 = Icon::new(IconName::FileDoc);
|
||||
let icon_2 = Icon::new(IconName::FileDoc);
|
||||
let icon_3 = Icon::new(IconName::FileDoc);
|
||||
|
|
|
@ -61,7 +61,7 @@ pub struct IconDecoration {
|
|||
|
||||
impl IconDecoration {
|
||||
/// Creates a new [`IconDecoration`].
|
||||
pub fn new(kind: IconDecorationKind, knockout_color: Hsla, cx: &WindowContext) -> Self {
|
||||
pub fn new(kind: IconDecorationKind, knockout_color: Hsla, cx: &App) -> Self {
|
||||
let color = cx.theme().colors().icon;
|
||||
let position = Point::default();
|
||||
|
||||
|
@ -116,7 +116,7 @@ impl IconDecoration {
|
|||
}
|
||||
|
||||
impl RenderOnce for IconDecoration {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
let foreground = svg()
|
||||
.absolute()
|
||||
.bottom_0()
|
||||
|
@ -151,7 +151,7 @@ impl RenderOnce for IconDecoration {
|
|||
}
|
||||
|
||||
impl ComponentPreview for IconDecoration {
|
||||
fn examples(cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut Window, cx: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
let all_kinds = IconDecorationKind::iter().collect::<Vec<_>>();
|
||||
|
||||
let examples = all_kinds
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(missing_docs)]
|
||||
use gpui::{svg, IntoElement, Rems, RenderOnce, Size, Styled, WindowContext};
|
||||
use gpui::{svg, App, IntoElement, Rems, RenderOnce, Size, Styled, Window};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{EnumIter, EnumString, IntoStaticStr};
|
||||
use ui_macros::{path_str, DerivePathStr};
|
||||
|
@ -69,7 +69,7 @@ impl Vector {
|
|||
}
|
||||
|
||||
impl RenderOnce for Vector {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let width = self.size.width;
|
||||
let height = self.size.height;
|
||||
|
||||
|
@ -97,7 +97,7 @@ pub mod story {
|
|||
pub struct VectorStory;
|
||||
|
||||
impl Render for VectorStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container().child(StorySection::new().children(VectorName::iter().map(
|
||||
|vector| StoryItem::new(format!("{:?}", vector), Vector::square(vector, rems(8.))),
|
||||
)))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use std::{cmp::Ordering, ops::Range, rc::Rc};
|
||||
|
||||
use gpui::{
|
||||
fill, point, size, AnyElement, AppContext, Bounds, Hsla, Point, UniformListDecoration, View,
|
||||
fill, point, size, AnyElement, App, Bounds, Entity, Hsla, Point, UniformListDecoration,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -21,7 +21,7 @@ pub struct IndentGuideColors {
|
|||
|
||||
impl IndentGuideColors {
|
||||
/// Returns the indent guide colors that should be used for panels.
|
||||
pub fn panel(cx: &AppContext) -> Self {
|
||||
pub fn panel(cx: &App) -> Self {
|
||||
Self {
|
||||
default: cx.theme().colors().panel_indent_guide,
|
||||
hover: cx.theme().colors().panel_indent_guide_hover,
|
||||
|
@ -33,27 +33,28 @@ impl IndentGuideColors {
|
|||
pub struct IndentGuides {
|
||||
colors: IndentGuideColors,
|
||||
indent_size: Pixels,
|
||||
compute_indents_fn: Box<dyn Fn(Range<usize>, &mut WindowContext) -> SmallVec<[usize; 64]>>,
|
||||
compute_indents_fn: Box<dyn Fn(Range<usize>, &mut Window, &mut App) -> SmallVec<[usize; 64]>>,
|
||||
render_fn: Option<
|
||||
Box<
|
||||
dyn Fn(
|
||||
RenderIndentGuideParams,
|
||||
&mut WindowContext,
|
||||
&mut Window,
|
||||
&mut App,
|
||||
) -> SmallVec<[RenderedIndentGuide; 12]>,
|
||||
>,
|
||||
>,
|
||||
on_click: Option<Rc<dyn Fn(&IndentGuideLayout, &mut WindowContext)>>,
|
||||
on_click: Option<Rc<dyn Fn(&IndentGuideLayout, &mut Window, &mut App)>>,
|
||||
}
|
||||
|
||||
pub fn indent_guides<V: Render>(
|
||||
view: View<V>,
|
||||
model: Entity<V>,
|
||||
indent_size: Pixels,
|
||||
colors: IndentGuideColors,
|
||||
compute_indents_fn: impl Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> SmallVec<[usize; 64]>
|
||||
compute_indents_fn: impl Fn(&mut V, Range<usize>, &mut Window, &mut Context<V>) -> SmallVec<[usize; 64]>
|
||||
+ 'static,
|
||||
) -> IndentGuides {
|
||||
let compute_indents_fn = Box::new(move |range, cx: &mut WindowContext| {
|
||||
view.update(cx, |this, cx| compute_indents_fn(this, range, cx))
|
||||
let compute_indents_fn = Box::new(move |range, window: &mut Window, cx: &mut App| {
|
||||
model.update(cx, |this, cx| compute_indents_fn(this, range, window, cx))
|
||||
});
|
||||
IndentGuides {
|
||||
colors,
|
||||
|
@ -68,7 +69,7 @@ impl IndentGuides {
|
|||
/// Sets the callback that will be called when the user clicks on an indent guide.
|
||||
pub fn on_click(
|
||||
mut self,
|
||||
on_click: impl Fn(&IndentGuideLayout, &mut WindowContext) + 'static,
|
||||
on_click: impl Fn(&IndentGuideLayout, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_click = Some(Rc::new(on_click));
|
||||
self
|
||||
|
@ -77,16 +78,17 @@ impl IndentGuides {
|
|||
/// Sets a custom callback that will be called when the indent guides need to be rendered.
|
||||
pub fn with_render_fn<V: Render>(
|
||||
mut self,
|
||||
view: View<V>,
|
||||
model: Entity<V>,
|
||||
render_fn: impl Fn(
|
||||
&mut V,
|
||||
RenderIndentGuideParams,
|
||||
&mut WindowContext,
|
||||
&mut Window,
|
||||
&mut App,
|
||||
) -> SmallVec<[RenderedIndentGuide; 12]>
|
||||
+ 'static,
|
||||
) -> Self {
|
||||
let render_fn = move |params, cx: &mut WindowContext| {
|
||||
view.update(cx, |this, cx| render_fn(this, params, cx))
|
||||
let render_fn = move |params, window: &mut Window, cx: &mut App| {
|
||||
model.update(cx, |this, cx| render_fn(this, params, window, cx))
|
||||
};
|
||||
self.render_fn = Some(Box::new(render_fn));
|
||||
self
|
||||
|
@ -141,7 +143,8 @@ mod uniform_list {
|
|||
bounds: Bounds<Pixels>,
|
||||
item_height: Pixels,
|
||||
item_count: usize,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> AnyElement {
|
||||
let mut visible_range = visible_range.clone();
|
||||
let includes_trailing_indent = visible_range.end < item_count;
|
||||
|
@ -151,7 +154,7 @@ mod uniform_list {
|
|||
if includes_trailing_indent {
|
||||
visible_range.end += 1;
|
||||
}
|
||||
let visible_entries = &(self.compute_indents_fn)(visible_range.clone(), cx);
|
||||
let visible_entries = &(self.compute_indents_fn)(visible_range.clone(), window, cx);
|
||||
let indent_guides = compute_indent_guides(
|
||||
&visible_entries,
|
||||
visible_range.start,
|
||||
|
@ -163,7 +166,7 @@ mod uniform_list {
|
|||
indent_size: self.indent_size,
|
||||
item_height,
|
||||
};
|
||||
custom_render(params, cx)
|
||||
custom_render(params, window, cx)
|
||||
} else {
|
||||
indent_guides
|
||||
.into_iter()
|
||||
|
@ -200,14 +203,15 @@ mod uniform_list {
|
|||
struct IndentGuidesElement {
|
||||
colors: IndentGuideColors,
|
||||
indent_guides: Rc<SmallVec<[RenderedIndentGuide; 12]>>,
|
||||
on_hovered_indent_guide_click: Option<Rc<dyn Fn(&IndentGuideLayout, &mut WindowContext)>>,
|
||||
on_hovered_indent_guide_click:
|
||||
Option<Rc<dyn Fn(&IndentGuideLayout, &mut Window, &mut App)>>,
|
||||
}
|
||||
|
||||
enum IndentGuidesElementPrepaintState {
|
||||
Static,
|
||||
Interactive {
|
||||
hitboxes: Rc<SmallVec<[Hitbox; 12]>>,
|
||||
on_hovered_indent_guide_click: Rc<dyn Fn(&IndentGuideLayout, &mut WindowContext)>,
|
||||
on_hovered_indent_guide_click: Rc<dyn Fn(&IndentGuideLayout, &mut Window, &mut App)>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -222,9 +226,10 @@ mod uniform_list {
|
|||
fn request_layout(
|
||||
&mut self,
|
||||
_id: Option<&gpui::GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> (gpui::LayoutId, Self::RequestLayoutState) {
|
||||
(cx.request_layout(gpui::Style::default(), []), ())
|
||||
(window.request_layout(gpui::Style::default(), [], cx), ())
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
|
@ -232,7 +237,8 @@ mod uniform_list {
|
|||
_id: Option<&gpui::GlobalElementId>,
|
||||
_bounds: Bounds<Pixels>,
|
||||
_request_layout: &mut Self::RequestLayoutState,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
_cx: &mut App,
|
||||
) -> Self::PrepaintState {
|
||||
if let Some(on_hovered_indent_guide_click) = self.on_hovered_indent_guide_click.clone()
|
||||
{
|
||||
|
@ -240,7 +246,7 @@ mod uniform_list {
|
|||
.indent_guides
|
||||
.as_ref()
|
||||
.iter()
|
||||
.map(|guide| cx.insert_hitbox(guide.hitbox.unwrap_or(guide.bounds), false))
|
||||
.map(|guide| window.insert_hitbox(guide.hitbox.unwrap_or(guide.bounds), false))
|
||||
.collect();
|
||||
Self::PrepaintState::Interactive {
|
||||
hitboxes: Rc::new(hitboxes),
|
||||
|
@ -257,7 +263,8 @@ mod uniform_list {
|
|||
_bounds: Bounds<Pixels>,
|
||||
_request_layout: &mut Self::RequestLayoutState,
|
||||
prepaint: &mut Self::PrepaintState,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
_cx: &mut App,
|
||||
) {
|
||||
match prepaint {
|
||||
IndentGuidesElementPrepaintState::Static => {
|
||||
|
@ -268,22 +275,22 @@ mod uniform_list {
|
|||
self.colors.default
|
||||
};
|
||||
|
||||
cx.paint_quad(fill(indent_guide.bounds, fill_color));
|
||||
window.paint_quad(fill(indent_guide.bounds, fill_color));
|
||||
}
|
||||
}
|
||||
IndentGuidesElementPrepaintState::Interactive {
|
||||
hitboxes,
|
||||
on_hovered_indent_guide_click,
|
||||
} => {
|
||||
cx.on_mouse_event({
|
||||
window.on_mouse_event({
|
||||
let hitboxes = hitboxes.clone();
|
||||
let indent_guides = self.indent_guides.clone();
|
||||
let on_hovered_indent_guide_click = on_hovered_indent_guide_click.clone();
|
||||
move |event: &MouseDownEvent, phase, cx| {
|
||||
move |event: &MouseDownEvent, phase, window, cx| {
|
||||
if phase == DispatchPhase::Bubble && event.button == MouseButton::Left {
|
||||
let mut active_hitbox_ix = None;
|
||||
for (i, hitbox) in hitboxes.iter().enumerate() {
|
||||
if hitbox.is_hovered(cx) {
|
||||
if hitbox.is_hovered(window) {
|
||||
active_hitbox_ix = Some(i);
|
||||
break;
|
||||
}
|
||||
|
@ -294,18 +301,18 @@ mod uniform_list {
|
|||
};
|
||||
|
||||
let active_indent_guide = &indent_guides[active_hitbox_ix].layout;
|
||||
on_hovered_indent_guide_click(active_indent_guide, cx);
|
||||
on_hovered_indent_guide_click(active_indent_guide, window, cx);
|
||||
|
||||
cx.stop_propagation();
|
||||
cx.prevent_default();
|
||||
window.prevent_default();
|
||||
}
|
||||
}
|
||||
});
|
||||
let mut hovered_hitbox_id = None;
|
||||
for (i, hitbox) in hitboxes.iter().enumerate() {
|
||||
cx.set_cursor_style(gpui::CursorStyle::PointingHand, hitbox);
|
||||
window.set_cursor_style(gpui::CursorStyle::PointingHand, hitbox);
|
||||
let indent_guide = &self.indent_guides[i];
|
||||
let fill_color = if hitbox.is_hovered(cx) {
|
||||
let fill_color = if hitbox.is_hovered(window) {
|
||||
hovered_hitbox_id = Some(hitbox.id);
|
||||
self.colors.hover
|
||||
} else if indent_guide.is_active {
|
||||
|
@ -314,16 +321,16 @@ mod uniform_list {
|
|||
self.colors.default
|
||||
};
|
||||
|
||||
cx.paint_quad(fill(indent_guide.bounds, fill_color));
|
||||
window.paint_quad(fill(indent_guide.bounds, fill_color));
|
||||
}
|
||||
|
||||
cx.on_mouse_event({
|
||||
window.on_mouse_event({
|
||||
let prev_hovered_hitbox_id = hovered_hitbox_id;
|
||||
let hitboxes = hitboxes.clone();
|
||||
move |_: &MouseMoveEvent, phase, cx| {
|
||||
move |_: &MouseMoveEvent, phase, window, _cx| {
|
||||
let mut hovered_hitbox_id = None;
|
||||
for hitbox in hitboxes.as_ref() {
|
||||
if hitbox.is_hovered(cx) {
|
||||
if hitbox.is_hovered(window) {
|
||||
hovered_hitbox_id = Some(hitbox.id);
|
||||
break;
|
||||
}
|
||||
|
@ -333,14 +340,14 @@ mod uniform_list {
|
|||
match (prev_hovered_hitbox_id, hovered_hitbox_id) {
|
||||
(Some(prev_id), Some(id)) => {
|
||||
if prev_id != id {
|
||||
cx.refresh();
|
||||
window.refresh();
|
||||
}
|
||||
}
|
||||
(None, Some(_)) => {
|
||||
cx.refresh();
|
||||
window.refresh();
|
||||
}
|
||||
(Some(_), None) => {
|
||||
cx.refresh();
|
||||
window.refresh();
|
||||
}
|
||||
(None, None) => {}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ impl Indicator {
|
|||
}
|
||||
|
||||
impl RenderOnce for Indicator {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let container = div().flex_none();
|
||||
let container = if let Some(border_color) = self.border_color {
|
||||
if matches!(self.kind, IndicatorKind::Dot | IndicatorKind::Bar) {
|
||||
|
@ -89,7 +89,7 @@ impl ComponentPreview for Indicator {
|
|||
"An indicator visually represents a status or state."
|
||||
}
|
||||
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group_with_title(
|
||||
"Types",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![allow(missing_docs)]
|
||||
use crate::PlatformStyle;
|
||||
use crate::{h_flex, prelude::*, Icon, IconName, IconSize};
|
||||
use gpui::{relative, Action, FocusHandle, IntoElement, Keystroke, WindowContext};
|
||||
use gpui::{relative, Action, App, FocusHandle, IntoElement, Keystroke, Window};
|
||||
|
||||
#[derive(Debug, IntoElement, Clone)]
|
||||
pub struct KeyBinding {
|
||||
|
@ -18,8 +18,12 @@ pub struct KeyBinding {
|
|||
impl KeyBinding {
|
||||
/// Returns the highest precedence keybinding for an action. This is the last binding added to
|
||||
/// the keymap. User bindings are added after built-in bindings so that they take precedence.
|
||||
pub fn for_action(action: &dyn Action, cx: &mut WindowContext) -> Option<Self> {
|
||||
let key_binding = cx.bindings_for_action(action).into_iter().rev().next()?;
|
||||
pub fn for_action(action: &dyn Action, window: &mut Window) -> Option<Self> {
|
||||
let key_binding = window
|
||||
.bindings_for_action(action)
|
||||
.into_iter()
|
||||
.rev()
|
||||
.next()?;
|
||||
Some(Self::new(key_binding))
|
||||
}
|
||||
|
||||
|
@ -27,9 +31,9 @@ impl KeyBinding {
|
|||
pub fn for_action_in(
|
||||
action: &dyn Action,
|
||||
focus: &FocusHandle,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
) -> Option<Self> {
|
||||
let key_binding = cx
|
||||
let key_binding = window
|
||||
.bindings_for_action_in(action, focus)
|
||||
.into_iter()
|
||||
.rev()
|
||||
|
@ -76,7 +80,7 @@ impl KeyBinding {
|
|||
}
|
||||
|
||||
impl RenderOnce for KeyBinding {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.debug_selector(|| {
|
||||
format!(
|
||||
|
@ -152,7 +156,7 @@ pub struct Key {
|
|||
}
|
||||
|
||||
impl RenderOnce for Key {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let single_char = self.key.len() == 1;
|
||||
|
||||
div()
|
||||
|
@ -187,7 +191,7 @@ pub struct KeyIcon {
|
|||
}
|
||||
|
||||
impl RenderOnce for KeyIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
Icon::new(self.icon)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
|
@ -201,8 +205,8 @@ impl KeyIcon {
|
|||
}
|
||||
|
||||
/// Returns a textual representation of the key binding for the given [`Action`].
|
||||
pub fn text_for_action(action: &dyn Action, cx: &WindowContext) -> Option<String> {
|
||||
let bindings = cx.bindings_for_action(action);
|
||||
pub fn text_for_action(action: &dyn Action, window: &Window) -> Option<String> {
|
||||
let bindings = window.bindings_for_action(action);
|
||||
let key_binding = bindings.last()?;
|
||||
Some(text_for_key_binding(key_binding, PlatformStyle::platform()))
|
||||
}
|
||||
|
@ -212,9 +216,9 @@ pub fn text_for_action(action: &dyn Action, cx: &WindowContext) -> Option<String
|
|||
pub fn text_for_action_in(
|
||||
action: &dyn Action,
|
||||
focus: &FocusHandle,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
) -> Option<String> {
|
||||
let bindings = cx.bindings_for_action_in(action, focus);
|
||||
let bindings = window.bindings_for_action_in(action, focus);
|
||||
let key_binding = bindings.last()?;
|
||||
Some(text_for_key_binding(key_binding, PlatformStyle::platform()))
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ pub fn highlight_ranges(
|
|||
}
|
||||
|
||||
impl RenderOnce for HighlightedLabel {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let highlight_color = cx.theme().colors().text_accent;
|
||||
|
||||
let highlights = highlight_ranges(
|
||||
|
@ -119,7 +119,7 @@ impl RenderOnce for HighlightedLabel {
|
|||
},
|
||||
);
|
||||
|
||||
let mut text_style = cx.text_style();
|
||||
let mut text_style = window.text_style();
|
||||
text_style.color = self.base.color.color(cx);
|
||||
|
||||
self.base
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(missing_docs)]
|
||||
|
||||
use gpui::{StyleRefinement, WindowContext};
|
||||
use gpui::{App, StyleRefinement, Window};
|
||||
|
||||
use crate::{prelude::*, LabelCommon, LabelLike, LabelSize, LineHeightStyle};
|
||||
|
||||
|
@ -175,7 +175,7 @@ impl LabelCommon for Label {
|
|||
}
|
||||
|
||||
impl RenderOnce for Label {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
self.base.child(self.label)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,9 +168,7 @@ impl ParentElement for LabelLike {
|
|||
}
|
||||
|
||||
impl RenderOnce for LabelLike {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let mut color = self.color.color(cx);
|
||||
if let Some(alpha) = self.alpha {
|
||||
color.fade_out(1.0 - alpha);
|
||||
|
@ -203,7 +201,10 @@ impl RenderOnce for LabelLike {
|
|||
this.overflow_x_hidden().text_ellipsis()
|
||||
})
|
||||
.text_color(color)
|
||||
.font_weight(self.weight.unwrap_or(settings.ui_font.weight))
|
||||
.font_weight(
|
||||
self.weight
|
||||
.unwrap_or(ThemeSettings::get_global(cx).ui_font.weight),
|
||||
)
|
||||
.children(self.children)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ impl From<AnyElement> for EmptyMessage {
|
|||
}
|
||||
|
||||
impl RenderOnce for List {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
v_flex()
|
||||
.w_full()
|
||||
.py(DynamicSpacing::Base04.rems(cx))
|
||||
|
|
|
@ -20,7 +20,7 @@ pub struct ListHeader {
|
|||
/// It will obscure the `end_slot` when visible.
|
||||
end_hover_slot: Option<AnyElement>,
|
||||
toggle: Option<bool>,
|
||||
on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||
on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
inset: bool,
|
||||
selected: bool,
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ impl ListHeader {
|
|||
|
||||
pub fn on_toggle(
|
||||
mut self,
|
||||
on_toggle: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||
on_toggle: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_toggle = Some(Arc::new(on_toggle));
|
||||
self
|
||||
|
@ -81,7 +81,7 @@ impl Toggleable for ListHeader {
|
|||
}
|
||||
|
||||
impl RenderOnce for ListHeader {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let ui_density = ThemeSettings::get_global(cx).ui_density;
|
||||
|
||||
h_flex()
|
||||
|
@ -120,7 +120,9 @@ impl RenderOnce for ListHeader {
|
|||
.children(self.start_slot)
|
||||
.child(Label::new(self.label.clone()).color(Color::Muted))
|
||||
.when_some(self.on_toggle, |this, on_toggle| {
|
||||
this.on_click(move |event, cx| on_toggle(event, cx))
|
||||
this.on_click(move |event, window, cx| {
|
||||
on_toggle(event, window, cx)
|
||||
})
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -33,10 +33,10 @@ pub struct ListItem {
|
|||
end_hover_slot: Option<AnyElement>,
|
||||
toggle: Option<bool>,
|
||||
inset: bool,
|
||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||
on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||
tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView + 'static>>,
|
||||
on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut WindowContext) + 'static>>,
|
||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>>,
|
||||
on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut Window, &mut App) + 'static>>,
|
||||
children: SmallVec<[AnyElement; 2]>,
|
||||
selectable: bool,
|
||||
outlined: bool,
|
||||
|
@ -80,20 +80,23 @@ impl ListItem {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||
pub fn on_click(
|
||||
mut self,
|
||||
handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_click = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_secondary_mouse_down(
|
||||
mut self,
|
||||
handler: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
|
||||
handler: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_secondary_mouse_down = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.tooltip = Some(Box::new(tooltip));
|
||||
self
|
||||
}
|
||||
|
@ -120,7 +123,7 @@ impl ListItem {
|
|||
|
||||
pub fn on_toggle(
|
||||
mut self,
|
||||
on_toggle: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||
on_toggle: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_toggle = Some(Arc::new(on_toggle));
|
||||
self
|
||||
|
@ -178,7 +181,7 @@ impl ParentElement for ListItem {
|
|||
}
|
||||
|
||||
impl RenderOnce for ListItem {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.id(self.id)
|
||||
.w_full()
|
||||
|
@ -256,8 +259,8 @@ impl RenderOnce for ListItem {
|
|||
.overflow_hidden()
|
||||
})
|
||||
.when_some(self.on_secondary_mouse_down, |this, on_mouse_down| {
|
||||
this.on_mouse_down(MouseButton::Right, move |event, cx| {
|
||||
(on_mouse_down)(event, cx)
|
||||
this.on_mouse_down(MouseButton::Right, move |event, window, cx| {
|
||||
(on_mouse_down)(event, window, cx)
|
||||
})
|
||||
})
|
||||
.when_some(self.tooltip, |this, tooltip| this.tooltip(tooltip))
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::prelude::*;
|
|||
pub struct ListSeparator;
|
||||
|
||||
impl RenderOnce for ListSeparator {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
div()
|
||||
.h_px()
|
||||
.w_full()
|
||||
|
|
|
@ -40,7 +40,7 @@ impl Toggleable for ListSubHeader {
|
|||
}
|
||||
|
||||
impl RenderOnce for ListSubHeader {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.flex_1()
|
||||
.w_full()
|
||||
|
|
|
@ -66,7 +66,7 @@ impl ParentElement for Modal {
|
|||
}
|
||||
|
||||
impl RenderOnce for Modal {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
v_flex()
|
||||
.id(self.id.clone())
|
||||
.size_full()
|
||||
|
@ -143,7 +143,7 @@ impl ParentElement for ModalHeader {
|
|||
}
|
||||
|
||||
impl RenderOnce for ModalHeader {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let mut children = self.children;
|
||||
|
||||
if self.headline.is_some() {
|
||||
|
@ -168,8 +168,8 @@ impl RenderOnce for ModalHeader {
|
|||
this.child(
|
||||
IconButton::new("back", IconName::ArrowLeft)
|
||||
.shape(IconButtonShape::Square)
|
||||
.on_click(|_, cx| {
|
||||
cx.dispatch_action(menu::Cancel.boxed_clone());
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(menu::Cancel.boxed_clone(), cx);
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
@ -178,8 +178,8 @@ impl RenderOnce for ModalHeader {
|
|||
this.child(
|
||||
IconButton::new("dismiss", IconName::Close)
|
||||
.shape(IconButtonShape::Square)
|
||||
.on_click(|_, cx| {
|
||||
cx.dispatch_action(menu::Cancel.boxed_clone());
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(menu::Cancel.boxed_clone(), cx);
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
@ -212,7 +212,7 @@ impl ParentElement for ModalRow {
|
|||
}
|
||||
|
||||
impl RenderOnce for ModalRow {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
h_flex().w_full().py_1().children(self.children)
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ impl ModalFooter {
|
|||
}
|
||||
|
||||
impl RenderOnce for ModalFooter {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.flex_none()
|
||||
.w_full()
|
||||
|
@ -323,7 +323,7 @@ impl ParentElement for Section {
|
|||
}
|
||||
|
||||
impl RenderOnce for Section {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let mut section_bg = cx.theme().colors().text;
|
||||
section_bg.fade_out(0.96);
|
||||
|
||||
|
@ -395,7 +395,7 @@ impl SectionHeader {
|
|||
}
|
||||
|
||||
impl RenderOnce for SectionHeader {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.id(self.label.clone())
|
||||
.w_full()
|
||||
|
|
|
@ -18,14 +18,14 @@ pub struct NavigableEntry {
|
|||
|
||||
impl NavigableEntry {
|
||||
/// Creates a new [NavigableEntry] for a given scroll handle.
|
||||
pub fn new(scroll_handle: &ScrollHandle, cx: &WindowContext) -> Self {
|
||||
pub fn new(scroll_handle: &ScrollHandle, cx: &mut App) -> Self {
|
||||
Self {
|
||||
focus_handle: cx.focus_handle(),
|
||||
scroll_anchor: Some(ScrollAnchor::for_handle(scroll_handle.clone())),
|
||||
}
|
||||
}
|
||||
/// Create a new [NavigableEntry] that cannot be scrolled to.
|
||||
pub fn focusable(cx: &WindowContext) -> Self {
|
||||
pub fn focusable(cx: &mut App) -> Self {
|
||||
Self {
|
||||
focus_handle: cx.focus_handle(),
|
||||
scroll_anchor: None,
|
||||
|
@ -51,43 +51,44 @@ impl Navigable {
|
|||
|
||||
fn find_focused(
|
||||
selectable_children: &[NavigableEntry],
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<usize> {
|
||||
selectable_children
|
||||
.iter()
|
||||
.position(|entry| entry.focus_handle.contains_focused(cx))
|
||||
.position(|entry| entry.focus_handle.contains_focused(window, cx))
|
||||
}
|
||||
}
|
||||
impl RenderOnce for Navigable {
|
||||
fn render(self, _: &mut WindowContext) -> impl crate::IntoElement {
|
||||
fn render(self, _window: &mut Window, _: &mut App) -> impl crate::IntoElement {
|
||||
div()
|
||||
.on_action({
|
||||
let children = self.selectable_children.clone();
|
||||
|
||||
move |_: &menu::SelectNext, cx| {
|
||||
let target = Self::find_focused(&children, cx)
|
||||
move |_: &menu::SelectNext, window, cx| {
|
||||
let target = Self::find_focused(&children, window, cx)
|
||||
.and_then(|index| {
|
||||
index.checked_add(1).filter(|index| *index < children.len())
|
||||
})
|
||||
.unwrap_or(0);
|
||||
if let Some(entry) = children.get(target) {
|
||||
entry.focus_handle.focus(cx);
|
||||
entry.focus_handle.focus(window);
|
||||
if let Some(anchor) = &entry.scroll_anchor {
|
||||
anchor.scroll_to(cx);
|
||||
anchor.scroll_to(window, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.on_action({
|
||||
let children = self.selectable_children;
|
||||
move |_: &menu::SelectPrev, cx| {
|
||||
let target = Self::find_focused(&children, cx)
|
||||
move |_: &menu::SelectPrev, window, cx| {
|
||||
let target = Self::find_focused(&children, window, cx)
|
||||
.and_then(|index| index.checked_sub(1))
|
||||
.or(children.len().checked_sub(1));
|
||||
if let Some(entry) = target.and_then(|target| children.get(target)) {
|
||||
entry.focus_handle.focus(cx);
|
||||
entry.focus_handle.focus(window);
|
||||
if let Some(anchor) = &entry.scroll_anchor {
|
||||
anchor.scroll_to(cx);
|
||||
anchor.scroll_to(window, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,19 +8,19 @@ use crate::{prelude::*, IconButtonShape};
|
|||
pub struct NumericStepper {
|
||||
id: ElementId,
|
||||
value: SharedString,
|
||||
on_decrement: Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
|
||||
on_increment: Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
|
||||
on_decrement: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||
on_increment: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||
/// Whether to reserve space for the reset button.
|
||||
reserve_space_for_reset: bool,
|
||||
on_reset: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||
on_reset: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
}
|
||||
|
||||
impl NumericStepper {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
value: impl Into<SharedString>,
|
||||
on_decrement: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||
on_increment: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||
on_decrement: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
on_increment: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
|
@ -39,7 +39,7 @@ impl NumericStepper {
|
|||
|
||||
pub fn on_reset(
|
||||
mut self,
|
||||
on_reset: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||
on_reset: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_reset = Some(Box::new(on_reset));
|
||||
self
|
||||
|
@ -47,7 +47,7 @@ impl NumericStepper {
|
|||
}
|
||||
|
||||
impl RenderOnce for NumericStepper {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let shape = IconButtonShape::Square;
|
||||
let icon_size = IconSize::Small;
|
||||
|
||||
|
@ -65,7 +65,7 @@ impl RenderOnce for NumericStepper {
|
|||
} else if self.reserve_space_for_reset {
|
||||
element.child(
|
||||
h_flex()
|
||||
.size(icon_size.square(cx))
|
||||
.size(icon_size.square(window, cx))
|
||||
.flex_none()
|
||||
.into_any_element(),
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use crate::prelude::*;
|
||||
use crate::v_flex;
|
||||
use gpui::{
|
||||
div, AnyElement, Element, IntoElement, ParentElement, Pixels, RenderOnce, Styled, WindowContext,
|
||||
div, AnyElement, App, Element, IntoElement, ParentElement, Pixels, RenderOnce, Styled, Window,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -44,7 +44,7 @@ pub struct Popover {
|
|||
}
|
||||
|
||||
impl RenderOnce for Popover {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.gap_1()
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use gpui::{
|
||||
anchored, deferred, div, point, prelude::FluentBuilder, px, size, AnyElement, Bounds, Corner,
|
||||
DismissEvent, DispatchPhase, Element, ElementId, GlobalElementId, HitboxId, InteractiveElement,
|
||||
IntoElement, LayoutId, Length, ManagedView, MouseDownEvent, ParentElement, Pixels, Point,
|
||||
Style, View, VisualContext, WindowContext,
|
||||
anchored, deferred, div, point, prelude::FluentBuilder, px, size, AnyElement, App, Bounds,
|
||||
Corner, DismissEvent, DispatchPhase, Element, ElementId, Entity, Focusable as _,
|
||||
GlobalElementId, HitboxId, InteractiveElement, IntoElement, LayoutId, Length, ManagedView,
|
||||
MouseDownEvent, ParentElement, Pixels, Point, Style, Window,
|
||||
};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
@ -19,7 +19,10 @@ impl<T: Clickable> Clickable for gpui::AnimationElement<T>
|
|||
where
|
||||
T: Clickable + 'static,
|
||||
{
|
||||
fn on_click(self, handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||
fn on_click(
|
||||
self,
|
||||
handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.map_element(|e| e.on_click(handler))
|
||||
}
|
||||
|
||||
|
@ -52,18 +55,18 @@ impl<M> Default for PopoverMenuHandle<M> {
|
|||
}
|
||||
|
||||
struct PopoverMenuHandleState<M> {
|
||||
menu_builder: Rc<dyn Fn(&mut WindowContext) -> Option<View<M>>>,
|
||||
menu: Rc<RefCell<Option<View<M>>>>,
|
||||
menu_builder: Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>>>,
|
||||
menu: Rc<RefCell<Option<Entity<M>>>>,
|
||||
}
|
||||
|
||||
impl<M: ManagedView> PopoverMenuHandle<M> {
|
||||
pub fn show(&self, cx: &mut WindowContext) {
|
||||
pub fn show(&self, window: &mut Window, cx: &mut App) {
|
||||
if let Some(state) = self.0.borrow().as_ref() {
|
||||
show_menu(&state.menu_builder, &state.menu, cx);
|
||||
show_menu(&state.menu_builder, &state.menu, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hide(&self, cx: &mut WindowContext) {
|
||||
pub fn hide(&self, cx: &mut App) {
|
||||
if let Some(state) = self.0.borrow().as_ref() {
|
||||
if let Some(menu) = state.menu.borrow().as_ref() {
|
||||
menu.update(cx, |_, cx| cx.emit(DismissEvent));
|
||||
|
@ -71,12 +74,12 @@ impl<M: ManagedView> PopoverMenuHandle<M> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toggle(&self, cx: &mut WindowContext) {
|
||||
pub fn toggle(&self, window: &mut Window, cx: &mut App) {
|
||||
if let Some(state) = self.0.borrow().as_ref() {
|
||||
if state.menu.borrow().is_some() {
|
||||
self.hide(cx);
|
||||
} else {
|
||||
self.show(cx);
|
||||
self.show(window, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,13 +91,13 @@ impl<M: ManagedView> PopoverMenuHandle<M> {
|
|||
.map_or(false, |state| state.menu.borrow().as_ref().is_some())
|
||||
}
|
||||
|
||||
pub fn is_focused(&self, cx: &WindowContext) -> bool {
|
||||
pub fn is_focused(&self, window: &Window, cx: &App) -> bool {
|
||||
self.0.borrow().as_ref().map_or(false, |state| {
|
||||
state
|
||||
.menu
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map_or(false, |view| view.focus_handle(cx).is_focused(cx))
|
||||
.map_or(false, |model| model.focus_handle(cx).is_focused(window))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -104,13 +107,13 @@ pub struct PopoverMenu<M: ManagedView> {
|
|||
child_builder: Option<
|
||||
Box<
|
||||
dyn FnOnce(
|
||||
Rc<RefCell<Option<View<M>>>>,
|
||||
Option<Rc<dyn Fn(&mut WindowContext) -> Option<View<M>> + 'static>>,
|
||||
Rc<RefCell<Option<Entity<M>>>>,
|
||||
Option<Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>> + 'static>>,
|
||||
) -> AnyElement
|
||||
+ 'static,
|
||||
>,
|
||||
>,
|
||||
menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> Option<View<M>> + 'static>>,
|
||||
menu_builder: Option<Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>> + 'static>>,
|
||||
anchor: Corner,
|
||||
attach: Option<Corner>,
|
||||
offset: Option<Point<Pixels>>,
|
||||
|
@ -138,7 +141,10 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn menu(mut self, f: impl Fn(&mut WindowContext) -> Option<View<M>> + 'static) -> Self {
|
||||
pub fn menu(
|
||||
mut self,
|
||||
f: impl Fn(&mut Window, &mut App) -> Option<Entity<M>> + 'static,
|
||||
) -> Self {
|
||||
self.menu_builder = Some(Rc::new(f));
|
||||
self
|
||||
}
|
||||
|
@ -153,7 +159,7 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
let open = menu.borrow().is_some();
|
||||
t.toggle_state(open)
|
||||
.when_some(builder, |el, builder| {
|
||||
el.on_click(move |_, cx| show_menu(&builder, &menu, cx))
|
||||
el.on_click(move |_event, window, cx| show_menu(&builder, &menu, window, cx))
|
||||
})
|
||||
.into_any_element()
|
||||
}));
|
||||
|
@ -188,10 +194,10 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
})
|
||||
}
|
||||
|
||||
fn resolved_offset(&self, cx: &WindowContext) -> Point<Pixels> {
|
||||
fn resolved_offset(&self, window: &mut Window) -> Point<Pixels> {
|
||||
self.offset.unwrap_or_else(|| {
|
||||
// Default offset = 4px padding + 1px border
|
||||
let offset = rems_from_px(5.) * cx.rem_size();
|
||||
let offset = rems_from_px(5.) * window.rem_size();
|
||||
match self.anchor {
|
||||
Corner::TopRight | Corner::BottomRight => point(offset, px(0.)),
|
||||
Corner::TopLeft | Corner::BottomLeft => point(-offset, px(0.)),
|
||||
|
@ -201,33 +207,35 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
}
|
||||
|
||||
fn show_menu<M: ManagedView>(
|
||||
builder: &Rc<dyn Fn(&mut WindowContext) -> Option<View<M>>>,
|
||||
menu: &Rc<RefCell<Option<View<M>>>>,
|
||||
cx: &mut WindowContext,
|
||||
builder: &Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>>>,
|
||||
menu: &Rc<RefCell<Option<Entity<M>>>>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
let Some(new_menu) = (builder)(cx) else {
|
||||
let Some(new_menu) = (builder)(window, cx) else {
|
||||
return;
|
||||
};
|
||||
let menu2 = menu.clone();
|
||||
let previous_focus_handle = cx.focused();
|
||||
let previous_focus_handle = window.focused(cx);
|
||||
|
||||
cx.subscribe(&new_menu, move |modal, _: &DismissEvent, cx| {
|
||||
if modal.focus_handle(cx).contains_focused(cx) {
|
||||
if let Some(previous_focus_handle) = previous_focus_handle.as_ref() {
|
||||
cx.focus(previous_focus_handle);
|
||||
window
|
||||
.subscribe(&new_menu, cx, move |modal, _: &DismissEvent, window, cx| {
|
||||
if modal.focus_handle(cx).contains_focused(window, cx) {
|
||||
if let Some(previous_focus_handle) = previous_focus_handle.as_ref() {
|
||||
window.focus(previous_focus_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
*menu2.borrow_mut() = None;
|
||||
cx.refresh();
|
||||
})
|
||||
.detach();
|
||||
cx.focus_view(&new_menu);
|
||||
*menu2.borrow_mut() = None;
|
||||
window.refresh();
|
||||
})
|
||||
.detach();
|
||||
window.focus(&new_menu.focus_handle(cx));
|
||||
*menu.borrow_mut() = Some(new_menu);
|
||||
cx.refresh();
|
||||
window.refresh();
|
||||
}
|
||||
|
||||
pub struct PopoverMenuElementState<M> {
|
||||
menu: Rc<RefCell<Option<View<M>>>>,
|
||||
menu: Rc<RefCell<Option<Entity<M>>>>,
|
||||
child_bounds: Option<Bounds<Pixels>>,
|
||||
}
|
||||
|
||||
|
@ -253,7 +261,7 @@ pub struct PopoverMenuFrameState<M: ManagedView> {
|
|||
child_layout_id: Option<LayoutId>,
|
||||
child_element: Option<AnyElement>,
|
||||
menu_element: Option<AnyElement>,
|
||||
menu_handle: Rc<RefCell<Option<View<M>>>>,
|
||||
menu_handle: Rc<RefCell<Option<Entity<M>>>>,
|
||||
}
|
||||
|
||||
impl<M: ManagedView> Element for PopoverMenu<M> {
|
||||
|
@ -267,16 +275,17 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
|
|||
fn request_layout(
|
||||
&mut self,
|
||||
global_id: Option<&GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> (gpui::LayoutId, Self::RequestLayoutState) {
|
||||
cx.with_element_state(
|
||||
window.with_element_state(
|
||||
global_id.unwrap(),
|
||||
|element_state: Option<PopoverMenuElementState<M>>, cx| {
|
||||
|element_state: Option<PopoverMenuElementState<M>>, window| {
|
||||
let element_state = element_state.unwrap_or_default();
|
||||
let mut menu_layout_id = None;
|
||||
|
||||
let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
|
||||
let offset = self.resolved_offset(cx);
|
||||
let offset = self.resolved_offset(window);
|
||||
let mut anchored = anchored()
|
||||
.snap_to_window_with_margin(px(8.))
|
||||
.anchor(self.anchor)
|
||||
|
@ -289,7 +298,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
|
|||
.with_priority(1)
|
||||
.into_any();
|
||||
|
||||
menu_layout_id = Some(element.request_layout(cx));
|
||||
menu_layout_id = Some(element.request_layout(window, cx));
|
||||
element
|
||||
});
|
||||
|
||||
|
@ -308,15 +317,18 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
|
|||
|
||||
let child_layout_id = child_element
|
||||
.as_mut()
|
||||
.map(|child_element| child_element.request_layout(cx));
|
||||
.map(|child_element| child_element.request_layout(window, cx));
|
||||
|
||||
let mut style = Style::default();
|
||||
if self.full_width {
|
||||
style.size = size(relative(1.).into(), Length::Auto);
|
||||
}
|
||||
|
||||
let layout_id =
|
||||
cx.request_layout(style, menu_layout_id.into_iter().chain(child_layout_id));
|
||||
let layout_id = window.request_layout(
|
||||
style,
|
||||
menu_layout_id.into_iter().chain(child_layout_id),
|
||||
cx,
|
||||
);
|
||||
|
||||
(
|
||||
(
|
||||
|
@ -339,25 +351,26 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
|
|||
global_id: Option<&GlobalElementId>,
|
||||
_bounds: Bounds<Pixels>,
|
||||
request_layout: &mut Self::RequestLayoutState,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<HitboxId> {
|
||||
if let Some(child) = request_layout.child_element.as_mut() {
|
||||
child.prepaint(cx);
|
||||
child.prepaint(window, cx);
|
||||
}
|
||||
|
||||
if let Some(menu) = request_layout.menu_element.as_mut() {
|
||||
menu.prepaint(cx);
|
||||
menu.prepaint(window, cx);
|
||||
}
|
||||
|
||||
request_layout.child_layout_id.map(|layout_id| {
|
||||
let bounds = cx.layout_bounds(layout_id);
|
||||
cx.with_element_state(global_id.unwrap(), |element_state, _cx| {
|
||||
let bounds = window.layout_bounds(layout_id);
|
||||
window.with_element_state(global_id.unwrap(), |element_state, _cx| {
|
||||
let mut element_state: PopoverMenuElementState<M> = element_state.unwrap();
|
||||
element_state.child_bounds = Some(bounds);
|
||||
((), element_state)
|
||||
});
|
||||
|
||||
cx.insert_hitbox(bounds, false).id
|
||||
window.insert_hitbox(bounds, false).id
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -367,21 +380,22 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
|
|||
_: Bounds<gpui::Pixels>,
|
||||
request_layout: &mut Self::RequestLayoutState,
|
||||
child_hitbox: &mut Option<HitboxId>,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
if let Some(mut child) = request_layout.child_element.take() {
|
||||
child.paint(cx);
|
||||
child.paint(window, cx);
|
||||
}
|
||||
|
||||
if let Some(mut menu) = request_layout.menu_element.take() {
|
||||
menu.paint(cx);
|
||||
menu.paint(window, cx);
|
||||
|
||||
if let Some(child_hitbox) = *child_hitbox {
|
||||
let menu_handle = request_layout.menu_handle.clone();
|
||||
// Mouse-downing outside the menu dismisses it, so we don't
|
||||
// want a click on the toggle to re-open it.
|
||||
cx.on_mouse_event(move |_: &MouseDownEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble && child_hitbox.is_hovered(cx) {
|
||||
window.on_mouse_event(move |_: &MouseDownEvent, phase, window, cx| {
|
||||
if phase == DispatchPhase::Bubble && child_hitbox.is_hovered(window) {
|
||||
if let Some(menu) = menu_handle.borrow().as_ref() {
|
||||
menu.update(cx, |_, cx| {
|
||||
cx.emit(DismissEvent);
|
||||
|
|
|
@ -10,7 +10,7 @@ pub struct RadioWithLabel {
|
|||
id: ElementId,
|
||||
label: Label,
|
||||
selected: bool,
|
||||
on_click: Arc<dyn Fn(&bool, &mut WindowContext) + 'static>,
|
||||
on_click: Arc<dyn Fn(&bool, &mut Window, &mut App) + 'static>,
|
||||
}
|
||||
|
||||
impl RadioWithLabel {
|
||||
|
@ -18,7 +18,7 @@ impl RadioWithLabel {
|
|||
id: impl Into<ElementId>,
|
||||
label: Label,
|
||||
selected: bool,
|
||||
on_click: impl Fn(&bool, &mut WindowContext) + 'static,
|
||||
on_click: impl Fn(&bool, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
|
@ -30,7 +30,7 @@ impl RadioWithLabel {
|
|||
}
|
||||
|
||||
impl RenderOnce for RadioWithLabel {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let inner_diameter = rems_from_px(6.);
|
||||
let outer_diameter = rems_from_px(16.);
|
||||
let border_width = rems_from_px(1.);
|
||||
|
@ -56,8 +56,8 @@ impl RenderOnce for RadioWithLabel {
|
|||
}),
|
||||
)
|
||||
.child(self.label)
|
||||
.on_click(move |_event, cx| {
|
||||
(self.on_click)(&true, cx);
|
||||
.on_click(move |_event, window, cx| {
|
||||
(self.on_click)(&true, window, cx);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,21 +3,22 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use gpui::{
|
||||
anchored, deferred, div, px, AnyElement, Bounds, Corner, DismissEvent, DispatchPhase, Element,
|
||||
ElementId, GlobalElementId, Hitbox, InteractiveElement, IntoElement, LayoutId, ManagedView,
|
||||
MouseButton, MouseDownEvent, ParentElement, Pixels, Point, View, VisualContext, WindowContext,
|
||||
anchored, deferred, div, px, AnyElement, App, Bounds, Corner, DismissEvent, DispatchPhase,
|
||||
Element, ElementId, Entity, Focusable as _, GlobalElementId, Hitbox, InteractiveElement,
|
||||
IntoElement, LayoutId, ManagedView, MouseButton, MouseDownEvent, ParentElement, Pixels, Point,
|
||||
Window,
|
||||
};
|
||||
|
||||
pub struct RightClickMenu<M: ManagedView> {
|
||||
id: ElementId,
|
||||
child_builder: Option<Box<dyn FnOnce(bool) -> AnyElement + 'static>>,
|
||||
menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> View<M> + 'static>>,
|
||||
menu_builder: Option<Rc<dyn Fn(&mut Window, &mut App) -> Entity<M> + 'static>>,
|
||||
anchor: Option<Corner>,
|
||||
attach: Option<Corner>,
|
||||
}
|
||||
|
||||
impl<M: ManagedView> RightClickMenu<M> {
|
||||
pub fn menu(mut self, f: impl Fn(&mut WindowContext) -> View<M> + 'static) -> Self {
|
||||
pub fn menu(mut self, f: impl Fn(&mut Window, &mut App) -> Entity<M> + 'static) -> Self {
|
||||
self.menu_builder = Some(Rc::new(f));
|
||||
self
|
||||
}
|
||||
|
@ -43,14 +44,15 @@ impl<M: ManagedView> RightClickMenu<M> {
|
|||
fn with_element_state<R>(
|
||||
&mut self,
|
||||
global_id: &GlobalElementId,
|
||||
cx: &mut WindowContext,
|
||||
f: impl FnOnce(&mut Self, &mut MenuHandleElementState<M>, &mut WindowContext) -> R,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
f: impl FnOnce(&mut Self, &mut MenuHandleElementState<M>, &mut Window, &mut App) -> R,
|
||||
) -> R {
|
||||
cx.with_optional_element_state::<MenuHandleElementState<M>, _>(
|
||||
window.with_optional_element_state::<MenuHandleElementState<M>, _>(
|
||||
Some(global_id),
|
||||
|element_state, cx| {
|
||||
|element_state, window| {
|
||||
let mut element_state = element_state.unwrap().unwrap_or_default();
|
||||
let result = f(self, &mut element_state, cx);
|
||||
let result = f(self, &mut element_state, window, cx);
|
||||
(result, Some(element_state))
|
||||
},
|
||||
)
|
||||
|
@ -69,7 +71,7 @@ pub fn right_click_menu<M: ManagedView>(id: impl Into<ElementId>) -> RightClickM
|
|||
}
|
||||
|
||||
pub struct MenuHandleElementState<M> {
|
||||
menu: Rc<RefCell<Option<View<M>>>>,
|
||||
menu: Rc<RefCell<Option<Entity<M>>>>,
|
||||
position: Rc<RefCell<Point<Pixels>>>,
|
||||
}
|
||||
|
||||
|
@ -113,49 +115,56 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
|
|||
fn request_layout(
|
||||
&mut self,
|
||||
id: Option<&GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> (gpui::LayoutId, Self::RequestLayoutState) {
|
||||
self.with_element_state(id.unwrap(), cx, |this, element_state, cx| {
|
||||
let mut menu_layout_id = None;
|
||||
self.with_element_state(
|
||||
id.unwrap(),
|
||||
window,
|
||||
cx,
|
||||
|this, element_state, window, cx| {
|
||||
let mut menu_layout_id = None;
|
||||
|
||||
let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
|
||||
let mut anchored = anchored().snap_to_window_with_margin(px(8.));
|
||||
if let Some(anchor) = this.anchor {
|
||||
anchored = anchored.anchor(anchor);
|
||||
}
|
||||
anchored = anchored.position(*element_state.position.borrow());
|
||||
let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
|
||||
let mut anchored = anchored().snap_to_window_with_margin(px(8.));
|
||||
if let Some(anchor) = this.anchor {
|
||||
anchored = anchored.anchor(anchor);
|
||||
}
|
||||
anchored = anchored.position(*element_state.position.borrow());
|
||||
|
||||
let mut element = deferred(anchored.child(div().occlude().child(menu.clone())))
|
||||
.with_priority(1)
|
||||
.into_any();
|
||||
let mut element = deferred(anchored.child(div().occlude().child(menu.clone())))
|
||||
.with_priority(1)
|
||||
.into_any();
|
||||
|
||||
menu_layout_id = Some(element.request_layout(cx));
|
||||
element
|
||||
});
|
||||
menu_layout_id = Some(element.request_layout(window, cx));
|
||||
element
|
||||
});
|
||||
|
||||
let mut child_element = this
|
||||
.child_builder
|
||||
.take()
|
||||
.map(|child_builder| (child_builder)(element_state.menu.borrow().is_some()));
|
||||
let mut child_element = this
|
||||
.child_builder
|
||||
.take()
|
||||
.map(|child_builder| (child_builder)(element_state.menu.borrow().is_some()));
|
||||
|
||||
let child_layout_id = child_element
|
||||
.as_mut()
|
||||
.map(|child_element| child_element.request_layout(cx));
|
||||
let child_layout_id = child_element
|
||||
.as_mut()
|
||||
.map(|child_element| child_element.request_layout(window, cx));
|
||||
|
||||
let layout_id = cx.request_layout(
|
||||
gpui::Style::default(),
|
||||
menu_layout_id.into_iter().chain(child_layout_id),
|
||||
);
|
||||
let layout_id = window.request_layout(
|
||||
gpui::Style::default(),
|
||||
menu_layout_id.into_iter().chain(child_layout_id),
|
||||
cx,
|
||||
);
|
||||
|
||||
(
|
||||
layout_id,
|
||||
RequestLayoutState {
|
||||
child_element,
|
||||
child_layout_id,
|
||||
menu_element,
|
||||
},
|
||||
)
|
||||
})
|
||||
(
|
||||
layout_id,
|
||||
RequestLayoutState {
|
||||
child_element,
|
||||
child_layout_id,
|
||||
menu_element,
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
|
@ -163,23 +172,24 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
|
|||
_id: Option<&GlobalElementId>,
|
||||
bounds: Bounds<Pixels>,
|
||||
request_layout: &mut Self::RequestLayoutState,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> PrepaintState {
|
||||
let hitbox = cx.insert_hitbox(bounds, false);
|
||||
let hitbox = window.insert_hitbox(bounds, false);
|
||||
|
||||
if let Some(child) = request_layout.child_element.as_mut() {
|
||||
child.prepaint(cx);
|
||||
child.prepaint(window, cx);
|
||||
}
|
||||
|
||||
if let Some(menu) = request_layout.menu_element.as_mut() {
|
||||
menu.prepaint(cx);
|
||||
menu.prepaint(window, cx);
|
||||
}
|
||||
|
||||
PrepaintState {
|
||||
hitbox,
|
||||
child_bounds: request_layout
|
||||
.child_layout_id
|
||||
.map(|layout_id| cx.layout_bounds(layout_id)),
|
||||
.map(|layout_id| window.layout_bounds(layout_id)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,65 +199,74 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
|
|||
_bounds: Bounds<gpui::Pixels>,
|
||||
request_layout: &mut Self::RequestLayoutState,
|
||||
prepaint_state: &mut Self::PrepaintState,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
self.with_element_state(id.unwrap(), cx, |this, element_state, cx| {
|
||||
if let Some(mut child) = request_layout.child_element.take() {
|
||||
child.paint(cx);
|
||||
}
|
||||
|
||||
if let Some(mut menu) = request_layout.menu_element.take() {
|
||||
menu.paint(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(builder) = this.menu_builder.take() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let attach = this.attach;
|
||||
let menu = element_state.menu.clone();
|
||||
let position = element_state.position.clone();
|
||||
let child_bounds = prepaint_state.child_bounds;
|
||||
|
||||
let hitbox_id = prepaint_state.hitbox.id;
|
||||
cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble
|
||||
&& event.button == MouseButton::Right
|
||||
&& hitbox_id.is_hovered(cx)
|
||||
{
|
||||
cx.stop_propagation();
|
||||
cx.prevent_default();
|
||||
|
||||
let new_menu = (builder)(cx);
|
||||
let menu2 = menu.clone();
|
||||
let previous_focus_handle = cx.focused();
|
||||
|
||||
cx.subscribe(&new_menu, move |modal, _: &DismissEvent, cx| {
|
||||
if modal.focus_handle(cx).contains_focused(cx) {
|
||||
if let Some(previous_focus_handle) = previous_focus_handle.as_ref() {
|
||||
cx.focus(previous_focus_handle);
|
||||
}
|
||||
}
|
||||
*menu2.borrow_mut() = None;
|
||||
cx.refresh();
|
||||
})
|
||||
.detach();
|
||||
cx.focus_view(&new_menu);
|
||||
*menu.borrow_mut() = Some(new_menu);
|
||||
*position.borrow_mut() = if let Some(child_bounds) = child_bounds {
|
||||
if let Some(attach) = attach {
|
||||
child_bounds.corner(attach)
|
||||
} else {
|
||||
cx.mouse_position()
|
||||
}
|
||||
} else {
|
||||
cx.mouse_position()
|
||||
};
|
||||
cx.refresh();
|
||||
self.with_element_state(
|
||||
id.unwrap(),
|
||||
window,
|
||||
cx,
|
||||
|this, element_state, window, cx| {
|
||||
if let Some(mut child) = request_layout.child_element.take() {
|
||||
child.paint(window, cx);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if let Some(mut menu) = request_layout.menu_element.take() {
|
||||
menu.paint(window, cx);
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(builder) = this.menu_builder.take() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let attach = this.attach;
|
||||
let menu = element_state.menu.clone();
|
||||
let position = element_state.position.clone();
|
||||
let child_bounds = prepaint_state.child_bounds;
|
||||
|
||||
let hitbox_id = prepaint_state.hitbox.id;
|
||||
window.on_mouse_event(move |event: &MouseDownEvent, phase, window, cx| {
|
||||
if phase == DispatchPhase::Bubble
|
||||
&& event.button == MouseButton::Right
|
||||
&& hitbox_id.is_hovered(window)
|
||||
{
|
||||
cx.stop_propagation();
|
||||
window.prevent_default();
|
||||
|
||||
let new_menu = (builder)(window, cx);
|
||||
let menu2 = menu.clone();
|
||||
let previous_focus_handle = window.focused(cx);
|
||||
|
||||
window
|
||||
.subscribe(&new_menu, cx, move |modal, _: &DismissEvent, window, cx| {
|
||||
if modal.focus_handle(cx).contains_focused(window, cx) {
|
||||
if let Some(previous_focus_handle) =
|
||||
previous_focus_handle.as_ref()
|
||||
{
|
||||
window.focus(previous_focus_handle);
|
||||
}
|
||||
}
|
||||
*menu2.borrow_mut() = None;
|
||||
window.refresh();
|
||||
})
|
||||
.detach();
|
||||
window.focus(&new_menu.focus_handle(cx));
|
||||
*menu.borrow_mut() = Some(new_menu);
|
||||
*position.borrow_mut() = if let Some(child_bounds) = child_bounds {
|
||||
if let Some(attach) = attach {
|
||||
child_bounds.corner(attach)
|
||||
} else {
|
||||
window.mouse_position()
|
||||
}
|
||||
} else {
|
||||
window.mouse_position()
|
||||
};
|
||||
window.refresh();
|
||||
}
|
||||
});
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ use std::{any::Any, cell::Cell, fmt::Debug, ops::Range, rc::Rc, sync::Arc};
|
|||
|
||||
use crate::{prelude::*, px, relative, IntoElement};
|
||||
use gpui::{
|
||||
point, quad, Along, Axis as ScrollbarAxis, Bounds, ContentMask, Corners, Edges, Element,
|
||||
point, quad, Along, App, Axis as ScrollbarAxis, Bounds, ContentMask, Corners, Edges, Element,
|
||||
ElementId, Entity, EntityId, GlobalElementId, Hitbox, Hsla, LayoutId, MouseDownEvent,
|
||||
MouseMoveEvent, MouseUpEvent, Pixels, Point, ScrollHandle, ScrollWheelEvent, Size, Style,
|
||||
UniformListScrollHandle, View, WindowContext,
|
||||
UniformListScrollHandle, Window,
|
||||
};
|
||||
|
||||
pub struct Scrollbar {
|
||||
|
@ -113,8 +113,8 @@ impl ScrollbarState {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set a parent view which should be notified whenever this Scrollbar gets a scroll event.
|
||||
pub fn parent_view<V: 'static>(mut self, v: &View<V>) -> Self {
|
||||
/// Set a parent model which should be notified whenever this Scrollbar gets a scroll event.
|
||||
pub fn parent_model<V: 'static>(mut self, v: &Entity<V>) -> Self {
|
||||
self.parent_id = Some(v.entity_id());
|
||||
self
|
||||
}
|
||||
|
@ -194,7 +194,8 @@ impl Element for Scrollbar {
|
|||
fn request_layout(
|
||||
&mut self,
|
||||
_id: Option<&GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> (LayoutId, Self::RequestLayoutState) {
|
||||
let mut style = Style::default();
|
||||
style.flex_grow = 1.;
|
||||
|
@ -208,7 +209,7 @@ impl Element for Scrollbar {
|
|||
style.size.height = px(12.).into();
|
||||
}
|
||||
|
||||
(cx.request_layout(style, None), ())
|
||||
(window.request_layout(style, None, cx), ())
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
|
@ -216,10 +217,11 @@ impl Element for Scrollbar {
|
|||
_id: Option<&GlobalElementId>,
|
||||
bounds: Bounds<Pixels>,
|
||||
_request_layout: &mut Self::RequestLayoutState,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
_: &mut App,
|
||||
) -> Self::PrepaintState {
|
||||
cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
|
||||
cx.insert_hitbox(bounds, false)
|
||||
window.with_content_mask(Some(ContentMask { bounds }), |window| {
|
||||
window.insert_hitbox(bounds, false)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -229,9 +231,10 @@ impl Element for Scrollbar {
|
|||
bounds: Bounds<Pixels>,
|
||||
_request_layout: &mut Self::RequestLayoutState,
|
||||
_prepaint: &mut Self::PrepaintState,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
|
||||
window.with_content_mask(Some(ContentMask { bounds }), |window| {
|
||||
let colors = cx.theme().colors();
|
||||
let thumb_background = colors
|
||||
.surface_background
|
||||
|
@ -282,7 +285,7 @@ impl Element for Scrollbar {
|
|||
thumb_bounds.size.height /= 1.5;
|
||||
Corners::all(thumb_bounds.size.height / 2.0)
|
||||
};
|
||||
cx.paint_quad(quad(
|
||||
window.paint_quad(quad(
|
||||
thumb_bounds,
|
||||
corners,
|
||||
thumb_background,
|
||||
|
@ -294,11 +297,11 @@ impl Element for Scrollbar {
|
|||
let kind = self.kind;
|
||||
let thumb_percentage_size = self.thumb.end - self.thumb.start;
|
||||
|
||||
cx.on_mouse_event({
|
||||
window.on_mouse_event({
|
||||
let scroll = scroll.clone();
|
||||
let state = self.state.clone();
|
||||
let axis = self.kind;
|
||||
move |event: &MouseDownEvent, phase, _cx| {
|
||||
move |event: &MouseDownEvent, phase, _, _| {
|
||||
if !(phase.bubble() && bounds.contains(&event.position)) {
|
||||
return;
|
||||
}
|
||||
|
@ -333,19 +336,20 @@ impl Element for Scrollbar {
|
|||
}
|
||||
}
|
||||
});
|
||||
cx.on_mouse_event({
|
||||
window.on_mouse_event({
|
||||
let scroll = scroll.clone();
|
||||
move |event: &ScrollWheelEvent, phase, cx| {
|
||||
move |event: &ScrollWheelEvent, phase, window, _| {
|
||||
if phase.bubble() && bounds.contains(&event.position) {
|
||||
let current_offset = scroll.offset();
|
||||
scroll
|
||||
.set_offset(current_offset + event.delta.pixel_delta(cx.line_height()));
|
||||
scroll.set_offset(
|
||||
current_offset + event.delta.pixel_delta(window.line_height()),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
let state = self.state.clone();
|
||||
let kind = self.kind;
|
||||
cx.on_mouse_event(move |event: &MouseMoveEvent, _, cx| {
|
||||
window.on_mouse_event(move |event: &MouseMoveEvent, _, _, cx| {
|
||||
if let Some(drag_state) = state.drag.get().filter(|_| event.dragging()) {
|
||||
if let Some(ContentSize {
|
||||
size: item_size, ..
|
||||
|
@ -375,7 +379,7 @@ impl Element for Scrollbar {
|
|||
};
|
||||
|
||||
if let Some(id) = state.parent_id {
|
||||
cx.notify(Some(id));
|
||||
cx.notify(id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -383,11 +387,11 @@ impl Element for Scrollbar {
|
|||
}
|
||||
});
|
||||
let state = self.state.clone();
|
||||
cx.on_mouse_event(move |_event: &MouseUpEvent, phase, cx| {
|
||||
window.on_mouse_event(move |_event: &MouseUpEvent, phase, _, cx| {
|
||||
if phase.bubble() {
|
||||
state.drag.take();
|
||||
if let Some(id) = state.parent_id {
|
||||
cx.notify(Some(id));
|
||||
cx.notify(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -31,7 +31,7 @@ impl ParentElement for SettingsContainer {
|
|||
}
|
||||
|
||||
impl RenderOnce for SettingsContainer {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
v_flex().px_2().gap_1().children(self.children)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ impl ParentElement for SettingsGroup {
|
|||
}
|
||||
|
||||
impl RenderOnce for SettingsGroup {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
v_flex()
|
||||
.p_1()
|
||||
.gap_2()
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{Avatar, AvatarAudioStatusIndicator};
|
|||
pub struct AvatarStory;
|
||||
|
||||
impl Render for AvatarStory {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<Avatar>())
|
||||
.child(
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{Button, ButtonStyle};
|
|||
pub struct ButtonStory;
|
||||
|
||||
impl Render for ButtonStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<Button>())
|
||||
.child(Story::label("Default"))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use gpui::{actions, Corner, Render, View};
|
||||
use gpui::{actions, Corner, Entity, Render};
|
||||
use story::Story;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
@ -6,29 +6,35 @@ use crate::{right_click_menu, ContextMenu, Label};
|
|||
|
||||
actions!(context_menu, [PrintCurrentDate, PrintBestFood]);
|
||||
|
||||
fn build_menu(cx: &mut WindowContext, header: impl Into<SharedString>) -> View<ContextMenu> {
|
||||
ContextMenu::build(cx, |menu, _| {
|
||||
fn build_menu(
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
header: impl Into<SharedString>,
|
||||
) -> Entity<ContextMenu> {
|
||||
ContextMenu::build(window, cx, |menu, _, _| {
|
||||
menu.header(header)
|
||||
.separator()
|
||||
.action("Print current time", Box::new(PrintCurrentDate))
|
||||
.entry("Print best food", Some(Box::new(PrintBestFood)), |cx| {
|
||||
cx.dispatch_action(Box::new(PrintBestFood))
|
||||
})
|
||||
.entry(
|
||||
"Print best food",
|
||||
Some(Box::new(PrintBestFood)),
|
||||
|window, cx| window.dispatch_action(Box::new(PrintBestFood), cx),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub struct ContextMenuStory;
|
||||
|
||||
impl Render for ContextMenuStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.on_action(|_: &PrintCurrentDate, _| {
|
||||
.on_action(|_: &PrintCurrentDate, _, _| {
|
||||
println!("printing unix time!");
|
||||
if let Ok(unix_time) = std::time::UNIX_EPOCH.elapsed() {
|
||||
println!("Current Unix time is {:?}", unix_time.as_secs());
|
||||
}
|
||||
})
|
||||
.on_action(|_: &PrintBestFood, _| {
|
||||
.on_action(|_: &PrintBestFood, _, _| {
|
||||
println!("burrito");
|
||||
})
|
||||
.flex()
|
||||
|
@ -42,14 +48,14 @@ impl Render for ContextMenuStory {
|
|||
.child(
|
||||
right_click_menu("test2")
|
||||
.trigger(Label::new("TOP LEFT"))
|
||||
.menu(move |cx| build_menu(cx, "top left")),
|
||||
.menu(move |window, cx| build_menu(window, cx, "top left")),
|
||||
)
|
||||
.child(
|
||||
right_click_menu("test1")
|
||||
.trigger(Label::new("BOTTOM LEFT"))
|
||||
.anchor(Corner::BottomLeft)
|
||||
.attach(Corner::TopLeft)
|
||||
.menu(move |cx| build_menu(cx, "bottom left")),
|
||||
.menu(move |window, cx| build_menu(window, cx, "bottom left")),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
|
@ -61,14 +67,14 @@ impl Render for ContextMenuStory {
|
|||
right_click_menu("test3")
|
||||
.trigger(Label::new("TOP RIGHT"))
|
||||
.anchor(Corner::TopRight)
|
||||
.menu(move |cx| build_menu(cx, "top right")),
|
||||
.menu(move |window, cx| build_menu(window, cx, "top right")),
|
||||
)
|
||||
.child(
|
||||
right_click_menu("test4")
|
||||
.trigger(Label::new("BOTTOM RIGHT"))
|
||||
.anchor(Corner::BottomRight)
|
||||
.attach(Corner::TopRight)
|
||||
.menu(move |cx| build_menu(cx, "bottom right")),
|
||||
.menu(move |window, cx| build_menu(window, cx, "bottom right")),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::Disclosure;
|
|||
pub struct DisclosureStory;
|
||||
|
||||
impl Render for DisclosureStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<Disclosure>())
|
||||
.child(Story::label("Toggled"))
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{Icon, IconName};
|
|||
pub struct IconStory;
|
||||
|
||||
impl Render for IconStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let icons = IconName::iter();
|
||||
|
||||
Story::container()
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{IconButton, IconName};
|
|||
pub struct IconButtonStory;
|
||||
|
||||
impl Render for IconButtonStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let default_button = StoryItem::new(
|
||||
"Default",
|
||||
IconButton::new("default_icon_button", IconName::Hash),
|
||||
|
@ -60,9 +60,11 @@ impl Render for IconButtonStory {
|
|||
|
||||
let with_on_click_button = StoryItem::new(
|
||||
"With `on_click`",
|
||||
IconButton::new("with_on_click_button", IconName::Ai).on_click(|_event, _cx| {
|
||||
println!("Clicked!");
|
||||
}),
|
||||
IconButton::new("with_on_click_button", IconName::Ai).on_click(
|
||||
|_event, _window, _cx| {
|
||||
println!("Clicked!");
|
||||
},
|
||||
),
|
||||
)
|
||||
.description("Displays an icon button which triggers an event on click.")
|
||||
.usage(
|
||||
|
@ -76,13 +78,13 @@ impl Render for IconButtonStory {
|
|||
let with_tooltip_button = StoryItem::new(
|
||||
"With `tooltip`",
|
||||
IconButton::new("with_tooltip_button", IconName::MessageBubbles)
|
||||
.tooltip(|cx| Tooltip::text("Open messages", cx)),
|
||||
.tooltip(Tooltip::text("Open messages")),
|
||||
)
|
||||
.description("Displays an icon button that has a tooltip when hovered.")
|
||||
.usage(
|
||||
r#"
|
||||
IconButton::new("with_tooltip_button", Icon::MessageBubbles)
|
||||
.tooltip(|cx| Tooltip::text("Open messages", cx))
|
||||
.tooltip(Tooltip::text_f("Open messages"))
|
||||
"#,
|
||||
);
|
||||
|
||||
|
@ -90,14 +92,14 @@ impl Render for IconButtonStory {
|
|||
"Selected with `tooltip`",
|
||||
IconButton::new("selected_with_tooltip_button", IconName::InlayHint)
|
||||
.toggle_state(true)
|
||||
.tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)),
|
||||
.tooltip(Tooltip::text("Toggle inlay hints")),
|
||||
)
|
||||
.description("Displays a selected icon button with tooltip.")
|
||||
.usage(
|
||||
r#"
|
||||
IconButton::new("selected_with_tooltip_button", Icon::InlayHint)
|
||||
.selected(true)
|
||||
.tooltip(|cx| Tooltip::text("Toggle inlay hints", cx))
|
||||
.tooltip(Tooltip::text_f("Toggle inlay hints"))
|
||||
"#,
|
||||
);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ pub fn binding(key: &str) -> gpui::KeyBinding {
|
|||
}
|
||||
|
||||
impl Render for KeybindingStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let all_modifier_permutations = ["ctrl", "alt", "cmd", "shift"].into_iter().permutations(2);
|
||||
|
||||
Story::container()
|
||||
|
|
|
@ -7,7 +7,7 @@ use story::Story;
|
|||
pub struct LabelStory;
|
||||
|
||||
impl Render for LabelStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<Label>())
|
||||
.child(Story::label("Default"))
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{List, ListItem};
|
|||
pub struct ListStory;
|
||||
|
||||
impl Render for ListStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<List>())
|
||||
.child(Story::label("Default"))
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{IconName, ListHeader};
|
|||
pub struct ListHeaderStory;
|
||||
|
||||
impl Render for ListHeaderStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<ListHeader>())
|
||||
.child(Story::label("Default"))
|
||||
|
|
|
@ -9,7 +9,7 @@ const OVERFLOWING_TEXT: &str = "Lorem ipsum dolor sit amet, consectetur adipisci
|
|||
pub struct ListItemStory;
|
||||
|
||||
impl Render for ListItemStory {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.bg(cx.theme().colors().background)
|
||||
.child(Story::title_for::<ListItem>())
|
||||
|
@ -85,18 +85,16 @@ impl Render for ListItemStory {
|
|||
)),
|
||||
)
|
||||
.child(Story::label("With `on_click`"))
|
||||
.child(
|
||||
ListItem::new("with_on_click")
|
||||
.child("Click me")
|
||||
.on_click(|_event, _cx| {
|
||||
println!("Clicked!");
|
||||
}),
|
||||
)
|
||||
.child(ListItem::new("with_on_click").child("Click me").on_click(
|
||||
|_event, _window, _cx| {
|
||||
println!("Clicked!");
|
||||
},
|
||||
))
|
||||
.child(Story::label("With `on_secondary_mouse_down`"))
|
||||
.child(
|
||||
ListItem::new("with_on_secondary_mouse_down")
|
||||
.child("Right click me")
|
||||
.on_secondary_mouse_down(|_event, _cx| {
|
||||
.on_secondary_mouse_down(|_event, _window, _cx| {
|
||||
println!("Right mouse down!");
|
||||
}),
|
||||
)
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{Indicator, Tab};
|
|||
pub struct TabStory;
|
||||
|
||||
impl Render for TabStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<Tab>())
|
||||
.child(Story::label("Default"))
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{prelude::*, Tab, TabBar, TabPosition};
|
|||
pub struct TabBarStory;
|
||||
|
||||
impl Render for TabBarStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let tab_count = 20;
|
||||
let selected_tab_index = 3;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{prelude::*, ToggleButton};
|
|||
pub struct ToggleButtonStory;
|
||||
|
||||
impl Render for ToggleButtonStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<ToggleButton>())
|
||||
.child(
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{prelude::*, ToolStrip, Tooltip};
|
|||
pub struct ToolStripStory;
|
||||
|
||||
impl Render for ToolStripStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Story::container()
|
||||
.child(Story::title_for::<ToolStrip>())
|
||||
.child(
|
||||
|
@ -16,15 +16,15 @@ impl Render for ToolStripStory {
|
|||
ToolStrip::vertical("tool_strip_example")
|
||||
.tool(
|
||||
IconButton::new("example_tool", IconName::AudioOn)
|
||||
.tooltip(|cx| Tooltip::text("Example tool", cx)),
|
||||
.tooltip(Tooltip::text("Example tool")),
|
||||
)
|
||||
.tool(
|
||||
IconButton::new("example_tool_2", IconName::MicMute)
|
||||
.tooltip(|cx| Tooltip::text("Example tool 2", cx)),
|
||||
.tooltip(Tooltip::text("Example tool 2")),
|
||||
)
|
||||
.tool(
|
||||
IconButton::new("example_tool_3", IconName::Screen)
|
||||
.tooltip(|cx| Tooltip::text("Example tool 3", cx)),
|
||||
.tooltip(Tooltip::text("Example tool 3")),
|
||||
),
|
||||
),
|
||||
)),
|
||||
|
|
|
@ -74,11 +74,11 @@ impl Tab {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn content_height(cx: &mut WindowContext) -> Pixels {
|
||||
pub fn content_height(cx: &mut App) -> Pixels {
|
||||
DynamicSpacing::Base32.px(cx) - px(1.)
|
||||
}
|
||||
|
||||
pub fn container_height(cx: &mut WindowContext) -> Pixels {
|
||||
pub fn container_height(cx: &mut App) -> Pixels {
|
||||
DynamicSpacing::Base32.px(cx)
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ impl ParentElement for Tab {
|
|||
|
||||
impl RenderOnce for Tab {
|
||||
#[allow(refining_impl_trait)]
|
||||
fn render(self, cx: &mut WindowContext) -> Stateful<Div> {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> Stateful<Div> {
|
||||
let (text_color, tab_bg, _tab_hover_bg, _tab_active_bg) = match self.selected {
|
||||
false => (
|
||||
cx.theme().colors().text_muted,
|
||||
|
|
|
@ -91,7 +91,7 @@ impl ParentElement for TabBar {
|
|||
}
|
||||
|
||||
impl RenderOnce for TabBar {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
div()
|
||||
.id(self.id)
|
||||
.group("tab_bar")
|
||||
|
|
|
@ -49,7 +49,7 @@ impl Table {
|
|||
self
|
||||
}
|
||||
|
||||
fn base_cell_style(cx: &WindowContext) -> Div {
|
||||
fn base_cell_style(cx: &mut App) -> Div {
|
||||
div()
|
||||
.px_1p5()
|
||||
.flex_1()
|
||||
|
@ -74,7 +74,7 @@ impl Table {
|
|||
}
|
||||
|
||||
impl RenderOnce for Table {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let header = div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
|
@ -160,7 +160,7 @@ impl ComponentPreview for Table {
|
|||
ExampleLabelSide::Top
|
||||
}
|
||||
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group(vec![
|
||||
single_example(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use gpui::{div, hsla, prelude::*, AnyView, ElementId, Hsla, IntoElement, Styled, WindowContext};
|
||||
use gpui::{div, hsla, prelude::*, AnyView, ElementId, Hsla, IntoElement, Styled, Window};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::utils::is_light;
|
||||
|
@ -41,10 +41,10 @@ pub struct Checkbox {
|
|||
id: ElementId,
|
||||
toggle_state: ToggleState,
|
||||
disabled: bool,
|
||||
on_click: Option<Box<dyn Fn(&ToggleState, &mut WindowContext) + 'static>>,
|
||||
on_click: Option<Box<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>>,
|
||||
filled: bool,
|
||||
style: ToggleStyle,
|
||||
tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
|
||||
tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||
}
|
||||
|
||||
impl Checkbox {
|
||||
|
@ -70,7 +70,7 @@ impl Checkbox {
|
|||
/// Binds a handler to the [`Checkbox`] that will be called when clicked.
|
||||
pub fn on_click(
|
||||
mut self,
|
||||
handler: impl Fn(&ToggleState, &mut WindowContext) + 'static,
|
||||
handler: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_click = Some(Box::new(handler));
|
||||
self
|
||||
|
@ -95,14 +95,14 @@ impl Checkbox {
|
|||
}
|
||||
|
||||
/// Sets the tooltip for the checkbox.
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.tooltip = Some(Box::new(tooltip));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Checkbox {
|
||||
fn bg_color(&self, cx: &WindowContext) -> Hsla {
|
||||
fn bg_color(&self, cx: &App) -> Hsla {
|
||||
let style = self.style.clone();
|
||||
match (style, self.filled) {
|
||||
(ToggleStyle::Ghost, false) => cx.theme().colors().ghost_element_background,
|
||||
|
@ -114,7 +114,7 @@ impl Checkbox {
|
|||
}
|
||||
}
|
||||
|
||||
fn border_color(&self, cx: &WindowContext) -> Hsla {
|
||||
fn border_color(&self, cx: &App) -> Hsla {
|
||||
if self.disabled {
|
||||
return cx.theme().colors().border_disabled;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ impl Checkbox {
|
|||
}
|
||||
|
||||
impl RenderOnce for Checkbox {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let group_id = format!("checkbox_group_{:?}", self.id);
|
||||
let icon = match self.toggle_state {
|
||||
ToggleState::Selected => Some(Icon::new(IconName::Check).size(IconSize::Small).color(
|
||||
|
@ -181,11 +181,13 @@ impl RenderOnce for Checkbox {
|
|||
.when_some(
|
||||
self.on_click.filter(|_| !self.disabled),
|
||||
|this, on_click| {
|
||||
this.on_click(move |_, cx| on_click(&self.toggle_state.inverse(), cx))
|
||||
this.on_click(move |_, window, cx| {
|
||||
on_click(&self.toggle_state.inverse(), window, cx)
|
||||
})
|
||||
},
|
||||
)
|
||||
.when_some(self.tooltip, |this, tooltip| {
|
||||
this.tooltip(move |cx| tooltip(cx))
|
||||
this.tooltip(move |window, cx| tooltip(window, cx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +198,7 @@ pub struct CheckboxWithLabel {
|
|||
id: ElementId,
|
||||
label: Label,
|
||||
checked: ToggleState,
|
||||
on_click: Arc<dyn Fn(&ToggleState, &mut WindowContext) + 'static>,
|
||||
on_click: Arc<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>,
|
||||
filled: bool,
|
||||
style: ToggleStyle,
|
||||
}
|
||||
|
@ -207,7 +209,7 @@ impl CheckboxWithLabel {
|
|||
id: impl Into<ElementId>,
|
||||
label: Label,
|
||||
checked: ToggleState,
|
||||
on_click: impl Fn(&ToggleState, &mut WindowContext) + 'static,
|
||||
on_click: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
|
@ -239,7 +241,7 @@ impl CheckboxWithLabel {
|
|||
}
|
||||
|
||||
impl RenderOnce for CheckboxWithLabel {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.gap(DynamicSpacing::Base08.rems(cx))
|
||||
.child(
|
||||
|
@ -248,16 +250,16 @@ impl RenderOnce for CheckboxWithLabel {
|
|||
.when(self.filled, Checkbox::fill)
|
||||
.on_click({
|
||||
let on_click = self.on_click.clone();
|
||||
move |checked, cx| {
|
||||
(on_click)(checked, cx);
|
||||
move |checked, window, cx| {
|
||||
(on_click)(checked, window, cx);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.id(SharedString::from(format!("{}-label", self.id)))
|
||||
.on_click(move |_event, cx| {
|
||||
(self.on_click)(&self.checked.inverse(), cx);
|
||||
.on_click(move |_event, window, cx| {
|
||||
(self.on_click)(&self.checked.inverse(), window, cx);
|
||||
})
|
||||
.child(self.label),
|
||||
)
|
||||
|
@ -272,7 +274,7 @@ pub struct Switch {
|
|||
id: ElementId,
|
||||
toggle_state: ToggleState,
|
||||
disabled: bool,
|
||||
on_click: Option<Box<dyn Fn(&ToggleState, &mut WindowContext) + 'static>>,
|
||||
on_click: Option<Box<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>>,
|
||||
label: Option<SharedString>,
|
||||
key_binding: Option<KeyBinding>,
|
||||
}
|
||||
|
@ -299,7 +301,7 @@ impl Switch {
|
|||
/// Binds a handler to the [`Switch`] that will be called when clicked.
|
||||
pub fn on_click(
|
||||
mut self,
|
||||
handler: impl Fn(&ToggleState, &mut WindowContext) + 'static,
|
||||
handler: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_click = Some(Box::new(handler));
|
||||
self
|
||||
|
@ -319,7 +321,7 @@ impl Switch {
|
|||
}
|
||||
|
||||
impl RenderOnce for Switch {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let is_on = self.toggle_state == ToggleState::Selected;
|
||||
let adjust_ratio = if is_light(cx) { 1.5 } else { 1.0 };
|
||||
let base_color = cx.theme().colors().text;
|
||||
|
@ -386,7 +388,9 @@ impl RenderOnce for Switch {
|
|||
.when_some(
|
||||
self.on_click.filter(|_| !self.disabled),
|
||||
|this, on_click| {
|
||||
this.on_click(move |_, cx| on_click(&self.toggle_state.inverse(), cx))
|
||||
this.on_click(move |_, window, cx| {
|
||||
on_click(&self.toggle_state.inverse(), window, cx)
|
||||
})
|
||||
},
|
||||
)
|
||||
.when_some(self.label, |this, label| {
|
||||
|
@ -401,7 +405,7 @@ impl ComponentPreview for Checkbox {
|
|||
"A checkbox lets people choose between a pair of opposing states, like enabled and disabled, using a different appearance to indicate each state."
|
||||
}
|
||||
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group_with_title(
|
||||
"Default",
|
||||
|
@ -595,18 +599,18 @@ impl ComponentPreview for Switch {
|
|||
"A switch toggles between two mutually exclusive states, typically used for enabling or disabling a setting."
|
||||
}
|
||||
|
||||
fn examples(_cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _cx: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group_with_title(
|
||||
"Default",
|
||||
vec![
|
||||
single_example(
|
||||
"Off",
|
||||
Switch::new("switch_off", ToggleState::Unselected).on_click(|_, _cx| {}),
|
||||
Switch::new("switch_off", ToggleState::Unselected).on_click(|_, _, _cx| {}),
|
||||
),
|
||||
single_example(
|
||||
"On",
|
||||
Switch::new("switch_on", ToggleState::Selected).on_click(|_, _cx| {}),
|
||||
Switch::new("switch_on", ToggleState::Selected).on_click(|_, _, _cx| {}),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -647,7 +651,7 @@ impl ComponentPreview for CheckboxWithLabel {
|
|||
"A checkbox with an associated label, allowing users to select an option while providing a descriptive text."
|
||||
}
|
||||
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![example_group(vec![
|
||||
single_example(
|
||||
"Unselected",
|
||||
|
@ -655,7 +659,7 @@ impl ComponentPreview for CheckboxWithLabel {
|
|||
"checkbox_with_label_unselected",
|
||||
Label::new("Always save on quit"),
|
||||
ToggleState::Unselected,
|
||||
|_, _| {},
|
||||
|_, _, _| {},
|
||||
),
|
||||
),
|
||||
single_example(
|
||||
|
@ -664,7 +668,7 @@ impl ComponentPreview for CheckboxWithLabel {
|
|||
"checkbox_with_label_indeterminate",
|
||||
Label::new("Always save on quit"),
|
||||
ToggleState::Indeterminate,
|
||||
|_, _| {},
|
||||
|_, _, _| {},
|
||||
),
|
||||
),
|
||||
single_example(
|
||||
|
@ -673,7 +677,7 @@ impl ComponentPreview for CheckboxWithLabel {
|
|||
"checkbox_with_label_selected",
|
||||
Label::new("Always save on quit"),
|
||||
ToggleState::Selected,
|
||||
|_, _| {},
|
||||
|_, _, _| {},
|
||||
),
|
||||
),
|
||||
])]
|
||||
|
|
|
@ -36,7 +36,7 @@ impl ToolStrip {
|
|||
}
|
||||
|
||||
impl RenderOnce for ToolStrip {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let group = format!("tool_strip_{}", self.id.clone());
|
||||
|
||||
div()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(missing_docs)]
|
||||
|
||||
use gpui::{Action, AnyView, FocusHandle, IntoElement, Render, VisualContext};
|
||||
use gpui::{Action, AnyView, AppContext as _, FocusHandle, IntoElement, Render};
|
||||
use settings::Settings;
|
||||
use theme::ThemeSettings;
|
||||
|
||||
|
@ -14,8 +14,8 @@ pub struct Tooltip {
|
|||
}
|
||||
|
||||
impl Tooltip {
|
||||
pub fn text(title: impl Into<SharedString>, cx: &mut WindowContext) -> AnyView {
|
||||
cx.new_view(|_cx| Self {
|
||||
pub fn simple(title: impl Into<SharedString>, cx: &mut App) -> AnyView {
|
||||
cx.new(|_| Self {
|
||||
title: title.into(),
|
||||
meta: None,
|
||||
key_binding: None,
|
||||
|
@ -23,15 +23,28 @@ impl Tooltip {
|
|||
.into()
|
||||
}
|
||||
|
||||
pub fn text(title: impl Into<SharedString>) -> impl Fn(&mut Window, &mut App) -> AnyView {
|
||||
let title = title.into();
|
||||
move |_, cx| {
|
||||
cx.new(|_| Self {
|
||||
title: title.clone(),
|
||||
meta: None,
|
||||
key_binding: None,
|
||||
})
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_action(
|
||||
title: impl Into<SharedString>,
|
||||
action: &dyn Action,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> AnyView {
|
||||
cx.new_view(|cx| Self {
|
||||
cx.new(|_| Self {
|
||||
title: title.into(),
|
||||
meta: None,
|
||||
key_binding: KeyBinding::for_action(action, cx),
|
||||
key_binding: KeyBinding::for_action(action, window),
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
@ -40,12 +53,13 @@ impl Tooltip {
|
|||
title: impl Into<SharedString>,
|
||||
action: &dyn Action,
|
||||
focus_handle: &FocusHandle,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> AnyView {
|
||||
cx.new_view(|cx| Self {
|
||||
cx.new(|_| Self {
|
||||
title: title.into(),
|
||||
meta: None,
|
||||
key_binding: KeyBinding::for_action_in(action, focus_handle, cx),
|
||||
key_binding: KeyBinding::for_action_in(action, focus_handle, window),
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
@ -54,12 +68,13 @@ impl Tooltip {
|
|||
title: impl Into<SharedString>,
|
||||
action: Option<&dyn Action>,
|
||||
meta: impl Into<SharedString>,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> AnyView {
|
||||
cx.new_view(|cx| Self {
|
||||
cx.new(|_| Self {
|
||||
title: title.into(),
|
||||
meta: Some(meta.into()),
|
||||
key_binding: action.and_then(|action| KeyBinding::for_action(action, cx)),
|
||||
key_binding: action.and_then(|action| KeyBinding::for_action(action, window)),
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
@ -69,13 +84,14 @@ impl Tooltip {
|
|||
action: Option<&dyn Action>,
|
||||
meta: impl Into<SharedString>,
|
||||
focus_handle: &FocusHandle,
|
||||
cx: &mut WindowContext,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> AnyView {
|
||||
cx.new_view(|cx| Self {
|
||||
cx.new(|_| Self {
|
||||
title: title.into(),
|
||||
meta: Some(meta.into()),
|
||||
key_binding: action
|
||||
.and_then(|action| KeyBinding::for_action_in(action, focus_handle, cx)),
|
||||
.and_then(|action| KeyBinding::for_action_in(action, focus_handle, window)),
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
@ -100,8 +116,8 @@ impl Tooltip {
|
|||
}
|
||||
|
||||
impl Render for Tooltip {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
tooltip_container(cx, |el, _| {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
tooltip_container(window, cx, |el, _, _| {
|
||||
el.child(
|
||||
h_flex()
|
||||
.gap_4()
|
||||
|
@ -118,8 +134,9 @@ impl Render for Tooltip {
|
|||
}
|
||||
|
||||
pub fn tooltip_container<V>(
|
||||
cx: &mut ViewContext<V>,
|
||||
f: impl FnOnce(Div, &mut ViewContext<V>) -> Div,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<V>,
|
||||
f: impl FnOnce(Div, &mut Window, &mut Context<V>) -> Div,
|
||||
) -> impl IntoElement {
|
||||
let ui_font = ThemeSettings::get_global(cx).ui_font.clone();
|
||||
|
||||
|
@ -132,7 +149,7 @@ pub fn tooltip_container<V>(
|
|||
.text_color(cx.theme().colors().text)
|
||||
.py_1()
|
||||
.px_2()
|
||||
.map(|el| f(el, cx)),
|
||||
.map(|el| f(el, window, cx)),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -141,7 +158,7 @@ pub struct LinkPreview {
|
|||
}
|
||||
|
||||
impl LinkPreview {
|
||||
pub fn new(url: &str, cx: &mut WindowContext) -> AnyView {
|
||||
pub fn new(url: &str, cx: &mut App) -> AnyView {
|
||||
let mut wrapped_url = String::new();
|
||||
for (i, ch) in url.chars().enumerate() {
|
||||
if i == 500 {
|
||||
|
@ -153,7 +170,7 @@ impl LinkPreview {
|
|||
}
|
||||
wrapped_url.push(ch);
|
||||
}
|
||||
cx.new_view(|_cx| LinkPreview {
|
||||
cx.new(|_| LinkPreview {
|
||||
link: wrapped_url.into(),
|
||||
})
|
||||
.into()
|
||||
|
@ -161,8 +178,8 @@ impl LinkPreview {
|
|||
}
|
||||
|
||||
impl Render for LinkPreview {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
tooltip_container(cx, |el, _| {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
tooltip_container(window, cx, |el, _, _| {
|
||||
el.child(
|
||||
Label::new(self.link.clone())
|
||||
.size(LabelSize::XSmall)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue