.cargo/config.toml 🔗
@@ -1,6 +1,3 @@
-[alias]
-xtask = "run --package xtask --"
-
[build]
# v0 mangling scheme provides more detailed backtraces around closures
rustflags = ["-C", "symbol-mangling-version=v0"]
Max Brunsfeld and Mikayla created
Co-authored-by: Mikayla <mikayla@zed.dev>
.cargo/config.toml | 3
Cargo.lock | 56 --
Cargo.toml | 6
crates/collab_ui/src/face_pile.rs | 2
crates/component_test/Cargo.toml | 18
crates/component_test/src/component_test.rs | 121 ----
crates/context_menu/Cargo.toml | 16
crates/context_menu/src/context_menu.rs | 528 ---------------------
crates/drag_and_drop/Cargo.toml | 16
crates/drag_and_drop/src/drag_and_drop.rs | 378 ---------------
crates/gpui/Cargo.toml | 2
crates/gpui/src/gpui.rs | 2
crates/gpui/src/styled.rs | 2
crates/gpui/tests/action_macros.rs | 6
crates/gpui2_macros/Cargo.toml | 14
crates/gpui2_macros/src/gpui2_macros.rs | 32 -
crates/gpui_macros/Cargo.toml | 8
crates/gpui_macros/src/derive_into_element.rs | 2
crates/gpui_macros/src/derive_render.rs | 2
crates/gpui_macros/src/gpui_macros.rs | 393 --------------
crates/gpui_macros/src/register_action.rs | 0
crates/gpui_macros/src/style_helpers.rs | 0
crates/gpui_macros/src/test.rs | 0
crates/rpc/src/peer.rs | 55 +-
crates/storybook/Cargo.toml | 1
crates/ui/src/components/popover.rs | 3
crates/xtask/Cargo.toml | 13
crates/xtask/src/cli.rs | 23
crates/xtask/src/main.rs | 29 -
29 files changed, 66 insertions(+), 1,665 deletions(-)
@@ -1,6 +1,3 @@
-[alias]
-xtask = "run --package xtask --"
-
[build]
# v0 mangling scheme provides more detailed backtraces around closures
rustflags = ["-C", "symbol-mangling-version=v0"]
@@ -1618,19 +1618,6 @@ dependencies = [
"zed_actions",
]
-[[package]]
-name = "component_test"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "gpui",
- "project",
- "settings",
- "theme",
- "util",
- "workspace",
-]
-
[[package]]
name = "concurrent-queue"
version = "2.2.0"
@@ -1665,17 +1652,6 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
-[[package]]
-name = "context_menu"
-version = "0.1.0"
-dependencies = [
- "gpui",
- "menu",
- "settings",
- "smallvec",
- "theme",
-]
-
[[package]]
name = "convert_case"
version = "0.4.0"
@@ -2354,14 +2330,6 @@ version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
-[[package]]
-name = "drag_and_drop"
-version = "0.1.0"
-dependencies = [
- "collections",
- "gpui",
-]
-
[[package]]
name = "dwrote"
version = "0.11.0"
@@ -3185,7 +3153,7 @@ dependencies = [
"font-kit",
"foreign-types",
"futures 0.3.28",
- "gpui2_macros",
+ "gpui_macros",
"image",
"itertools 0.10.5",
"lazy_static",
@@ -3225,20 +3193,10 @@ dependencies = [
"waker-fn",
]
-[[package]]
-name = "gpui2_macros"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
[[package]]
name = "gpui_macros"
version = "0.1.0"
dependencies = [
- "lazy_static",
"proc-macro2",
"quote",
"syn 1.0.109",
@@ -7677,6 +7635,7 @@ dependencies = [
"story",
"strum",
"theme",
+ "ui",
"util",
]
@@ -9936,17 +9895,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
-[[package]]
-name = "xtask"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "clap 4.4.4",
- "schemars",
- "serde_json",
- "theme",
-]
-
[[package]]
name = "yaml-rust"
version = "0.4.5"
@@ -15,15 +15,12 @@ members = [
"crates/collab_ui",
"crates/collections",
"crates/command_palette",
- "crates/component_test",
- "crates/context_menu",
"crates/copilot",
"crates/copilot_button",
"crates/db",
"crates/refineable",
"crates/refineable/derive_refineable",
"crates/diagnostics",
- "crates/drag_and_drop",
"crates/editor",
"crates/feature_flags",
"crates/feedback",
@@ -36,7 +33,7 @@ members = [
"crates/gpui",
"crates/gpui_macros",
"crates/gpui",
- "crates/gpui2_macros",
+ "crates/gpui_macros",
"crates/install_cli",
"crates/journal",
"crates/journal",
@@ -85,7 +82,6 @@ members = [
"crates/vcs_menu",
"crates/workspace",
"crates/welcome",
- "crates/xtask",
"crates/zed",
"crates/zed_actions",
]
@@ -1,5 +1,5 @@
use gpui::{
- div, AnyElement, ElementId, IntoElement, ParentElement, RenderOnce, Styled, WindowContext,
+ div, AnyElement, IntoElement, ParentElement, RenderOnce, Styled, WindowContext,
};
use smallvec::SmallVec;
@@ -1,18 +0,0 @@
-[package]
-name = "component_test"
-version = "0.1.0"
-edition = "2021"
-publish = false
-
-[lib]
-path = "src/component_test.rs"
-doctest = false
-
-[dependencies]
-anyhow.workspace = true
-gpui = { path = "../gpui" }
-settings = { path = "../settings" }
-util = { path = "../util" }
-theme = { path = "../theme" }
-workspace = { path = "../workspace" }
-project = { path = "../project" }
@@ -1,121 +0,0 @@
-use gpui::{
- actions,
- elements::{Component, Flex, ParentElement, SafeStylable},
- AppContext, Element, Entity, ModelHandle, Task, View, ViewContext, ViewHandle, WeakViewHandle,
-};
-use project::Project;
-use theme::components::{action_button::Button, label::Label, ComponentExt};
-use workspace::{
- item::Item, register_deserializable_item, ItemId, Pane, PaneBackdrop, Workspace, WorkspaceId,
-};
-
-pub fn init(cx: &mut AppContext) {
- cx.add_action(ComponentTest::toggle_disclosure);
- cx.add_action(ComponentTest::toggle_toggle);
- cx.add_action(ComponentTest::deploy);
- register_deserializable_item::<ComponentTest>(cx);
-}
-
-actions!(
- test,
- [NoAction, ToggleDisclosure, ToggleToggle, NewComponentTest]
-);
-
-struct ComponentTest {
- disclosed: bool,
- toggled: bool,
-}
-
-impl ComponentTest {
- fn new() -> Self {
- Self {
- disclosed: false,
- toggled: false,
- }
- }
-
- fn deploy(workspace: &mut Workspace, _: &NewComponentTest, cx: &mut ViewContext<Workspace>) {
- workspace.add_item(Box::new(cx.add_view(|_| ComponentTest::new())), cx);
- }
-
- fn toggle_disclosure(&mut self, _: &ToggleDisclosure, cx: &mut ViewContext<Self>) {
- self.disclosed = !self.disclosed;
- cx.notify();
- }
-
- fn toggle_toggle(&mut self, _: &ToggleToggle, cx: &mut ViewContext<Self>) {
- self.toggled = !self.toggled;
- cx.notify();
- }
-}
-
-impl Entity for ComponentTest {
- type Event = ();
-}
-
-impl View for ComponentTest {
- fn ui_name() -> &'static str {
- "Component Test"
- }
-
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> gpui::AnyElement<Self> {
- let theme = theme::current(cx);
-
- PaneBackdrop::new(
- cx.view_id(),
- Flex::column()
- .with_spacing(10.)
- .with_child(
- Button::action(NoAction)
- .with_tooltip("Here's what a tooltip looks like", theme.tooltip.clone())
- .with_contents(Label::new("Click me!"))
- .with_style(theme.component_test.button.clone())
- .element(),
- )
- .with_child(
- Button::action(ToggleToggle)
- .with_tooltip("Here's what a tooltip looks like", theme.tooltip.clone())
- .with_contents(Label::new("Toggle me!"))
- .toggleable(self.toggled)
- .with_style(theme.component_test.toggle.clone())
- .element(),
- )
- .with_child(
- Label::new("A disclosure")
- .disclosable(Some(self.disclosed), Box::new(ToggleDisclosure))
- .with_style(theme.component_test.disclosure.clone())
- .element(),
- )
- .constrained()
- .with_width(200.)
- .aligned()
- .into_any(),
- )
- .into_any()
- }
-}
-
-impl Item for ComponentTest {
- fn tab_content<V: 'static>(
- &self,
- _: Option<usize>,
- style: &theme::Tab,
- _: &AppContext,
- ) -> gpui::AnyElement<V> {
- gpui::elements::Label::new("Component test", style.label.clone()).into_any()
- }
-
- fn serialized_item_kind() -> Option<&'static str> {
- Some("ComponentTest")
- }
-
- fn deserialize(
- _project: ModelHandle<Project>,
- _workspace: WeakViewHandle<Workspace>,
- _workspace_id: WorkspaceId,
- _item_id: ItemId,
- cx: &mut ViewContext<Pane>,
- ) -> Task<anyhow::Result<ViewHandle<Self>>> {
- Task::ready(Ok(cx.add_view(|_| Self::new())))
- }
-}
@@ -1,16 +0,0 @@
-[package]
-name = "context_menu"
-version = "0.1.0"
-edition = "2021"
-publish = false
-
-[lib]
-path = "src/context_menu.rs"
-doctest = false
-
-[dependencies]
-gpui = { path = "../gpui" }
-menu = { path = "../menu" }
-settings = { path = "../settings" }
-theme = { path = "../theme" }
-smallvec.workspace = true
@@ -1,528 +0,0 @@
-use gpui::{
- anyhow::{self, anyhow},
- elements::*,
- geometry::vector::Vector2F,
- keymap_matcher::KeymapContext,
- platform::{CursorStyle, MouseButton},
- Action, AnyViewHandle, AppContext, Axis, Entity, MouseState, SizeConstraint, Subscription,
- View, ViewContext,
-};
-use menu::*;
-use std::{any::TypeId, borrow::Cow, sync::Arc, time::Duration};
-
-pub fn init(cx: &mut AppContext) {
- cx.add_action(ContextMenu::select_first);
- cx.add_action(ContextMenu::select_last);
- cx.add_action(ContextMenu::select_next);
- cx.add_action(ContextMenu::select_prev);
- cx.add_action(ContextMenu::confirm);
- cx.add_action(ContextMenu::cancel);
-}
-
-pub type StaticItem = Box<dyn Fn(&mut AppContext) -> AnyElement<ContextMenu>>;
-
-type ContextMenuItemBuilder =
- Box<dyn Fn(&mut MouseState, &theme::ContextMenuItem) -> AnyElement<ContextMenu>>;
-
-pub enum ContextMenuItemLabel {
- String(Cow<'static, str>),
- Element(ContextMenuItemBuilder),
-}
-
-impl From<Cow<'static, str>> for ContextMenuItemLabel {
- fn from(s: Cow<'static, str>) -> Self {
- Self::String(s)
- }
-}
-
-impl From<&'static str> for ContextMenuItemLabel {
- fn from(s: &'static str) -> Self {
- Self::String(s.into())
- }
-}
-
-impl From<String> for ContextMenuItemLabel {
- fn from(s: String) -> Self {
- Self::String(s.into())
- }
-}
-
-impl<T> From<T> for ContextMenuItemLabel
-where
- T: 'static + Fn(&mut MouseState, &theme::ContextMenuItem) -> AnyElement<ContextMenu>,
-{
- fn from(f: T) -> Self {
- Self::Element(Box::new(f))
- }
-}
-
-pub enum ContextMenuItemAction {
- Action(Box<dyn Action>),
- Handler(Arc<dyn Fn(&mut ViewContext<ContextMenu>)>),
-}
-
-impl Clone for ContextMenuItemAction {
- fn clone(&self) -> Self {
- match self {
- Self::Action(action) => Self::Action(action.boxed_clone()),
- Self::Handler(handler) => Self::Handler(handler.clone()),
- }
- }
-}
-
-pub enum ContextMenuItem {
- Item {
- label: ContextMenuItemLabel,
- action: ContextMenuItemAction,
- },
- Static(StaticItem),
- Separator,
-}
-
-impl ContextMenuItem {
- pub fn action(label: impl Into<ContextMenuItemLabel>, action: impl 'static + Action) -> Self {
- Self::Item {
- label: label.into(),
- action: ContextMenuItemAction::Action(Box::new(action)),
- }
- }
-
- pub fn handler(
- label: impl Into<ContextMenuItemLabel>,
- handler: impl 'static + Fn(&mut ViewContext<ContextMenu>),
- ) -> Self {
- Self::Item {
- label: label.into(),
- action: ContextMenuItemAction::Handler(Arc::new(handler)),
- }
- }
-
- pub fn separator() -> Self {
- Self::Separator
- }
-
- fn is_action(&self) -> bool {
- matches!(self, Self::Item { .. })
- }
-
- fn action_id(&self) -> Option<TypeId> {
- match self {
- ContextMenuItem::Item { action, .. } => match action {
- ContextMenuItemAction::Action(action) => Some(action.id()),
- ContextMenuItemAction::Handler(_) => None,
- },
- ContextMenuItem::Static(..) | ContextMenuItem::Separator => None,
- }
- }
-}
-
-pub struct ContextMenu {
- show_count: usize,
- anchor_position: Vector2F,
- anchor_corner: AnchorCorner,
- position_mode: OverlayPositionMode,
- items: Vec<ContextMenuItem>,
- selected_index: Option<usize>,
- visible: bool,
- delay_cancel: bool,
- previously_focused_view_id: Option<usize>,
- parent_view_id: usize,
- _actions_observation: Subscription,
-}
-
-impl Entity for ContextMenu {
- type Event = ();
-}
-
-impl View for ContextMenu {
- fn ui_name() -> &'static str {
- "ContextMenu"
- }
-
- fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
- Self::reset_to_default_keymap_context(keymap);
- keymap.add_identifier("menu");
- }
-
- fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
- if !self.visible {
- return Empty::new().into_any();
- }
-
- // Render the menu once at minimum width.
- let mut collapsed_menu = self.render_menu_for_measurement(cx);
- let expanded_menu =
- self.render_menu(cx)
- .constrained()
- .dynamically(move |constraint, view, cx| {
- SizeConstraint::strict_along(
- Axis::Horizontal,
- collapsed_menu.layout(constraint, view, cx).0.x(),
- )
- });
-
- Overlay::new(expanded_menu)
- .with_hoverable(true)
- .with_fit_mode(OverlayFitMode::SnapToWindow)
- .with_anchor_position(self.anchor_position)
- .with_anchor_corner(self.anchor_corner)
- .with_position_mode(self.position_mode)
- .into_any()
- }
-
- fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
- self.reset(cx);
- }
-}
-
-impl ContextMenu {
- pub fn new(parent_view_id: usize, cx: &mut ViewContext<Self>) -> Self {
- Self {
- show_count: 0,
- delay_cancel: false,
- anchor_position: Default::default(),
- anchor_corner: AnchorCorner::TopLeft,
- position_mode: OverlayPositionMode::Window,
- items: Default::default(),
- selected_index: Default::default(),
- visible: Default::default(),
- previously_focused_view_id: Default::default(),
- parent_view_id,
- _actions_observation: cx.observe_actions(Self::action_dispatched),
- }
- }
-
- pub fn visible(&self) -> bool {
- self.visible
- }
-
- fn action_dispatched(&mut self, action_id: TypeId, cx: &mut ViewContext<Self>) {
- if let Some(ix) = self
- .items
- .iter()
- .position(|item| item.action_id() == Some(action_id))
- {
- self.selected_index = Some(ix);
- cx.notify();
- cx.spawn(|this, mut cx| async move {
- cx.background().timer(Duration::from_millis(50)).await;
- this.update(&mut cx, |this, cx| this.cancel(&Default::default(), cx))?;
- anyhow::Ok(())
- })
- .detach_and_log_err(cx);
- }
- }
-
- fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
- if let Some(ix) = self.selected_index {
- if let Some(ContextMenuItem::Item { action, .. }) = self.items.get(ix) {
- match action {
- ContextMenuItemAction::Action(action) => {
- let window = cx.window();
- let view_id = self.parent_view_id;
- let action = action.boxed_clone();
- cx.app_context()
- .spawn(|mut cx| async move {
- window
- .dispatch_action(view_id, action.as_ref(), &mut cx)
- .ok_or_else(|| anyhow!("window was closed"))
- })
- .detach_and_log_err(cx);
- }
- ContextMenuItemAction::Handler(handler) => handler(cx),
- }
- self.reset(cx);
- }
- }
- }
-
- pub fn delay_cancel(&mut self) {
- self.delay_cancel = true;
- }
-
- fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
- if !self.delay_cancel {
- self.reset(cx);
- let show_count = self.show_count;
- cx.defer(move |this, cx| {
- if cx.handle().is_focused(cx) && this.show_count == show_count {
- (**cx).focus(this.previously_focused_view_id.take());
- }
- });
- } else {
- self.delay_cancel = false;
- }
- }
-
- fn reset(&mut self, cx: &mut ViewContext<Self>) {
- self.items.clear();
- self.visible = false;
- self.selected_index.take();
- cx.notify();
- }
-
- fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext<Self>) {
- self.selected_index = self.items.iter().position(|item| item.is_action());
- cx.notify();
- }
-
- fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
- for (ix, item) in self.items.iter().enumerate().rev() {
- if item.is_action() {
- self.selected_index = Some(ix);
- cx.notify();
- break;
- }
- }
- }
-
- fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
- if let Some(ix) = self.selected_index {
- for (ix, item) in self.items.iter().enumerate().skip(ix + 1) {
- if item.is_action() {
- self.selected_index = Some(ix);
- cx.notify();
- break;
- }
- }
- } else {
- self.select_first(&Default::default(), cx);
- }
- }
-
- fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
- if let Some(ix) = self.selected_index {
- for (ix, item) in self.items.iter().enumerate().take(ix).rev() {
- if item.is_action() {
- self.selected_index = Some(ix);
- cx.notify();
- break;
- }
- }
- } else {
- self.select_last(&Default::default(), cx);
- }
- }
-
- pub fn toggle(
- &mut self,
- anchor_position: Vector2F,
- anchor_corner: AnchorCorner,
- items: Vec<ContextMenuItem>,
- cx: &mut ViewContext<Self>,
- ) {
- if self.visible() {
- self.cancel(&Cancel, cx);
- } else {
- let mut items = items.into_iter().peekable();
- if items.peek().is_some() {
- self.items = items.collect();
- self.anchor_position = anchor_position;
- self.anchor_corner = anchor_corner;
- self.visible = true;
- self.show_count += 1;
- if !cx.is_self_focused() {
- self.previously_focused_view_id = cx.focused_view_id();
- }
- cx.focus_self();
- } else {
- self.visible = false;
- }
- }
- cx.notify();
- }
-
- pub fn show(
- &mut self,
- anchor_position: Vector2F,
- anchor_corner: AnchorCorner,
- items: Vec<ContextMenuItem>,
- cx: &mut ViewContext<Self>,
- ) {
- let mut items = items.into_iter().peekable();
- if items.peek().is_some() {
- self.items = items.collect();
- self.anchor_position = anchor_position;
- self.anchor_corner = anchor_corner;
- self.visible = true;
- self.show_count += 1;
- if !cx.is_self_focused() {
- self.previously_focused_view_id = cx.focused_view_id();
- }
- cx.focus_self();
- } else {
- self.visible = false;
- }
- cx.notify();
- }
-
- pub fn set_position_mode(&mut self, mode: OverlayPositionMode) {
- self.position_mode = mode;
- }
-
- fn render_menu_for_measurement(&self, cx: &mut ViewContext<Self>) -> impl Element<ContextMenu> {
- let style = theme::current(cx).context_menu.clone();
- Flex::row()
- .with_child(
- Flex::column().with_children(self.items.iter().enumerate().map(|(ix, item)| {
- match item {
- ContextMenuItem::Item { label, .. } => {
- let style = style.item.in_state(self.selected_index == Some(ix));
- let style = style.style_for(&mut Default::default());
-
- match label {
- ContextMenuItemLabel::String(label) => {
- Label::new(label.to_string(), style.label.clone())
- .contained()
- .with_style(style.container)
- .into_any()
- }
- ContextMenuItemLabel::Element(element) => {
- element(&mut Default::default(), style)
- }
- }
- }
-
- ContextMenuItem::Static(f) => f(cx),
-
- ContextMenuItem::Separator => Empty::new()
- .collapsed()
- .contained()
- .with_style(style.separator)
- .constrained()
- .with_height(1.)
- .into_any(),
- }
- })),
- )
- .with_child(
- Flex::column()
- .with_children(self.items.iter().enumerate().map(|(ix, item)| {
- match item {
- ContextMenuItem::Item { action, .. } => {
- let style = style.item.in_state(self.selected_index == Some(ix));
- let style = style.style_for(&mut Default::default());
-
- match action {
- ContextMenuItemAction::Action(action) => KeystrokeLabel::new(
- self.parent_view_id,
- action.boxed_clone(),
- style.keystroke.container,
- style.keystroke.text.clone(),
- )
- .into_any(),
- ContextMenuItemAction::Handler(_) => Empty::new().into_any(),
- }
- }
-
- ContextMenuItem::Static(_) => Empty::new().into_any(),
-
- ContextMenuItem::Separator => Empty::new()
- .collapsed()
- .constrained()
- .with_height(1.)
- .contained()
- .with_style(style.separator)
- .into_any(),
- }
- }))
- .contained()
- .with_margin_left(style.keystroke_margin),
- )
- .contained()
- .with_style(style.container)
- }
-
- fn render_menu(&self, cx: &mut ViewContext<Self>) -> impl Element<ContextMenu> {
- enum Menu {}
- enum MenuItem {}
-
- let style = theme::current(cx).context_menu.clone();
-
- MouseEventHandler::new::<Menu, _>(0, cx, |_, cx| {
- Flex::column()
- .with_children(self.items.iter().enumerate().map(|(ix, item)| {
- match item {
- ContextMenuItem::Item { label, action } => {
- let action = action.clone();
- let view_id = self.parent_view_id;
- MouseEventHandler::new::<MenuItem, _>(ix, cx, |state, _| {
- let style = style.item.in_state(self.selected_index == Some(ix));
- let style = style.style_for(state);
- let keystroke = match &action {
- ContextMenuItemAction::Action(action) => Some(
- KeystrokeLabel::new(
- view_id,
- action.boxed_clone(),
- style.keystroke.container,
- style.keystroke.text.clone(),
- )
- .flex_float(),
- ),
- ContextMenuItemAction::Handler(_) => None,
- };
-
- Flex::row()
- .with_child(match label {
- ContextMenuItemLabel::String(label) => {
- Label::new(label.clone(), style.label.clone())
- .contained()
- .into_any()
- }
- ContextMenuItemLabel::Element(element) => {
- element(state, style)
- }
- })
- .with_children(keystroke)
- .contained()
- .with_style(style.container)
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_up(MouseButton::Left, |_, _, _| {}) // Capture these events
- .on_down(MouseButton::Left, |_, _, _| {}) // Capture these events
- .on_click(MouseButton::Left, move |_, menu, cx| {
- menu.cancel(&Default::default(), cx);
- let window = cx.window();
- match &action {
- ContextMenuItemAction::Action(action) => {
- let action = action.boxed_clone();
- cx.app_context()
- .spawn(|mut cx| async move {
- window
- .dispatch_action(
- view_id,
- action.as_ref(),
- &mut cx,
- )
- .ok_or_else(|| anyhow!("window was closed"))
- })
- .detach_and_log_err(cx);
- }
- ContextMenuItemAction::Handler(handler) => handler(cx),
- }
- })
- .on_drag(MouseButton::Left, |_, _, _| {})
- .into_any()
- }
-
- ContextMenuItem::Static(f) => f(cx),
-
- ContextMenuItem::Separator => Empty::new()
- .constrained()
- .with_height(1.)
- .contained()
- .with_style(style.separator)
- .into_any(),
- }
- }))
- .contained()
- .with_style(style.container)
- })
- .on_down_out(MouseButton::Left, |_, this, cx| {
- this.cancel(&Default::default(), cx);
- })
- .on_down_out(MouseButton::Right, |_, this, cx| {
- this.cancel(&Default::default(), cx);
- })
- }
-}
@@ -1,16 +0,0 @@
-[package]
-name = "drag_and_drop"
-version = "0.1.0"
-edition = "2021"
-publish = false
-
-[lib]
-path = "src/drag_and_drop.rs"
-doctest = false
-
-[dependencies]
-collections = { path = "../collections" }
-gpui = { path = "../gpui" }
-
-[dev-dependencies]
-gpui = { path = "../gpui", features = ["test-support"] }
@@ -1,378 +0,0 @@
-use std::{any::Any, rc::Rc};
-
-use collections::HashSet;
-use gpui::{
- elements::{Empty, MouseEventHandler, Overlay},
- geometry::{rect::RectF, vector::Vector2F},
- platform::{CursorStyle, Modifiers, MouseButton},
- scene::{MouseDown, MouseDrag},
- AnyElement, AnyWindowHandle, Element, View, ViewContext, WeakViewHandle, WindowContext,
-};
-
-const DEAD_ZONE: f32 = 4.;
-
-enum State<V> {
- Down {
- region_offset: Vector2F,
- region: RectF,
- },
- DeadZone {
- region_offset: Vector2F,
- region: RectF,
- },
- Dragging {
- modifiers: Modifiers,
- window: AnyWindowHandle,
- position: Vector2F,
- region_offset: Vector2F,
- region: RectF,
- payload: Rc<dyn Any + 'static>,
- render: Rc<dyn Fn(&Modifiers, Rc<dyn Any>, &mut ViewContext<V>) -> AnyElement<V>>,
- },
- Canceled,
-}
-
-impl<V> Clone for State<V> {
- fn clone(&self) -> Self {
- match self {
- &State::Down {
- region_offset,
- region,
- } => State::Down {
- region_offset,
- region,
- },
- &State::DeadZone {
- region_offset,
- region,
- } => State::DeadZone {
- region_offset,
- region,
- },
- State::Dragging {
- modifiers,
- window,
- position,
- region_offset,
- region,
- payload,
- render,
- } => Self::Dragging {
- window: window.clone(),
- position: position.clone(),
- region_offset: region_offset.clone(),
- region: region.clone(),
- payload: payload.clone(),
- render: render.clone(),
- modifiers: modifiers.clone(),
- },
- State::Canceled => State::Canceled,
- }
- }
-}
-
-pub struct DragAndDrop<V> {
- containers: HashSet<WeakViewHandle<V>>,
- currently_dragged: Option<State<V>>,
-}
-
-impl<V> Default for DragAndDrop<V> {
- fn default() -> Self {
- Self {
- containers: Default::default(),
- currently_dragged: Default::default(),
- }
- }
-}
-
-impl<V: 'static> DragAndDrop<V> {
- pub fn register_container(&mut self, handle: WeakViewHandle<V>) {
- self.containers.insert(handle);
- }
-
- pub fn currently_dragged<T: Any>(&self, window: AnyWindowHandle) -> Option<(Vector2F, Rc<T>)> {
- self.currently_dragged.as_ref().and_then(|state| {
- if let State::Dragging {
- position,
- payload,
- window: window_dragged_from,
- ..
- } = state
- {
- if &window != window_dragged_from {
- return None;
- }
-
- payload
- .is::<T>()
- .then(|| payload.clone().downcast::<T>().ok())
- .flatten()
- .map(|payload| (position.clone(), payload))
- } else {
- None
- }
- })
- }
-
- pub fn any_currently_dragged(&self, window: AnyWindowHandle) -> bool {
- self.currently_dragged
- .as_ref()
- .map(|state| {
- if let State::Dragging {
- window: window_dragged_from,
- ..
- } = state
- {
- if &window != window_dragged_from {
- return false;
- }
-
- true
- } else {
- false
- }
- })
- .unwrap_or(false)
- }
-
- pub fn drag_started(event: MouseDown, cx: &mut WindowContext) {
- cx.update_global(|this: &mut Self, _| {
- this.currently_dragged = Some(State::Down {
- region_offset: event.position - event.region.origin(),
- region: event.region,
- });
- })
- }
-
- pub fn dragging<T: Any>(
- event: MouseDrag,
- payload: Rc<T>,
- cx: &mut WindowContext,
- render: Rc<impl 'static + Fn(&Modifiers, &T, &mut ViewContext<V>) -> AnyElement<V>>,
- ) {
- let window = cx.window();
- cx.update_global(|this: &mut Self, cx| {
- this.notify_containers_for_window(window, cx);
-
- match this.currently_dragged.as_ref() {
- Some(&State::Down {
- region_offset,
- region,
- })
- | Some(&State::DeadZone {
- region_offset,
- region,
- }) => {
- if (event.position - (region.origin() + region_offset)).length() > DEAD_ZONE {
- this.currently_dragged = Some(State::Dragging {
- modifiers: event.modifiers,
- window,
- region_offset,
- region,
- position: event.position,
- payload,
- render: Rc::new(move |modifiers, payload, cx| {
- render(modifiers, payload.downcast_ref::<T>().unwrap(), cx)
- }),
- });
- } else {
- this.currently_dragged = Some(State::DeadZone {
- region_offset,
- region,
- })
- }
- }
- Some(&State::Dragging {
- region_offset,
- region,
- modifiers,
- ..
- }) => {
- this.currently_dragged = Some(State::Dragging {
- modifiers,
- window,
- region_offset,
- region,
- position: event.position,
- payload,
- render: Rc::new(move |modifiers, payload, cx| {
- render(modifiers, payload.downcast_ref::<T>().unwrap(), cx)
- }),
- });
- }
- _ => {}
- }
- });
- }
-
- pub fn update_modifiers(new_modifiers: Modifiers, cx: &mut ViewContext<V>) -> bool {
- let result = cx.update_global(|this: &mut Self, _| match &mut this.currently_dragged {
- Some(state) => match state {
- State::Dragging { modifiers, .. } => {
- *modifiers = new_modifiers;
- true
- }
- _ => false,
- },
- None => false,
- });
-
- if result {
- cx.notify();
- }
-
- result
- }
-
- pub fn render(cx: &mut ViewContext<V>) -> Option<AnyElement<V>> {
- enum DraggedElementHandler {}
- cx.global::<Self>()
- .currently_dragged
- .clone()
- .and_then(|state| {
- match state {
- State::Down { .. } => None,
- State::DeadZone { .. } => None,
- State::Dragging {
- modifiers,
- window,
- region_offset,
- position,
- region,
- payload,
- render,
- } => {
- if cx.window() != window {
- return None;
- }
-
- let position = (position - region_offset).round();
- Some(
- Overlay::new(
- MouseEventHandler::new::<DraggedElementHandler, _>(
- 0,
- cx,
- |_, cx| render(&modifiers, payload, cx),
- )
- .with_cursor_style(CursorStyle::Arrow)
- .on_up(MouseButton::Left, |_, _, cx| {
- cx.window_context().defer(|cx| {
- cx.update_global::<Self, _, _>(|this, cx| {
- this.finish_dragging(cx)
- });
- });
- cx.propagate_event();
- })
- .on_up_out(MouseButton::Left, |_, _, cx| {
- cx.window_context().defer(|cx| {
- cx.update_global::<Self, _, _>(|this, cx| {
- this.finish_dragging(cx)
- });
- });
- })
- // Don't block hover events or invalidations
- .with_hoverable(false)
- .constrained()
- .with_width(region.width())
- .with_height(region.height()),
- )
- .with_anchor_position(position)
- .into_any(),
- )
- }
-
- State::Canceled => Some(
- MouseEventHandler::new::<DraggedElementHandler, _>(0, cx, |_, _| {
- Empty::new().constrained().with_width(0.).with_height(0.)
- })
- .on_up(MouseButton::Left, |_, _, cx| {
- cx.window_context().defer(|cx| {
- cx.update_global::<Self, _, _>(|this, _| {
- this.currently_dragged = None;
- });
- });
- })
- .on_up_out(MouseButton::Left, |_, _, cx| {
- cx.window_context().defer(|cx| {
- cx.update_global::<Self, _, _>(|this, _| {
- this.currently_dragged = None;
- });
- });
- })
- .into_any(),
- ),
- }
- })
- }
-
- pub fn cancel_dragging<P: Any>(&mut self, cx: &mut WindowContext) {
- if let Some(State::Dragging {
- payload, window, ..
- }) = &self.currently_dragged
- {
- if payload.is::<P>() {
- let window = *window;
- self.currently_dragged = Some(State::Canceled);
- self.notify_containers_for_window(window, cx);
- }
- }
- }
-
- fn finish_dragging(&mut self, cx: &mut WindowContext) {
- if let Some(State::Dragging { window, .. }) = self.currently_dragged.take() {
- self.notify_containers_for_window(window, cx);
- }
- }
-
- fn notify_containers_for_window(&mut self, window: AnyWindowHandle, cx: &mut WindowContext) {
- self.containers.retain(|container| {
- if let Some(container) = container.upgrade(cx) {
- if container.window() == window {
- container.update(cx, |_, cx| cx.notify());
- }
- true
- } else {
- false
- }
- });
- }
-}
-
-pub trait Draggable<V> {
- fn as_draggable<D: View, P: Any>(
- self,
- payload: P,
- render: impl 'static + Fn(&Modifiers, &P, &mut ViewContext<D>) -> AnyElement<D>,
- ) -> Self
- where
- Self: Sized;
-}
-
-impl<V: 'static> Draggable<V> for MouseEventHandler<V> {
- fn as_draggable<D: View, P: Any>(
- self,
- payload: P,
- render: impl 'static + Fn(&Modifiers, &P, &mut ViewContext<D>) -> AnyElement<D>,
- ) -> Self
- where
- Self: Sized,
- {
- let payload = Rc::new(payload);
- let render = Rc::new(render);
- self.on_down(MouseButton::Left, move |e, _, cx| {
- cx.propagate_event();
- DragAndDrop::<D>::drag_started(e, cx);
- })
- .on_drag(MouseButton::Left, move |e, _, cx| {
- if e.end {
- cx.update_global::<DragAndDrop<D>, _, _>(|drag_and_drop, cx| {
- drag_and_drop.finish_dragging(cx)
- })
- } else {
- let payload = payload.clone();
- let render = render.clone();
- DragAndDrop::<D>::dragging(e, payload, cx, render)
- }
- })
- }
-}
@@ -15,7 +15,7 @@ doctest = false
[dependencies]
collections = { path = "../collections" }
-gpui2_macros = { path = "../gpui2_macros" }
+gpui_macros = { path = "../gpui_macros" }
util = { path = "../util" }
sum_tree = { path = "../sum_tree" }
sqlez = { path = "../sqlez" }
@@ -47,7 +47,7 @@ pub use element::*;
pub use elements::*;
pub use executor::*;
pub use geometry::*;
-pub use gpui2_macros::*;
+pub use gpui_macros::*;
pub use image_cache::*;
pub use input::*;
pub use interactive::*;
@@ -10,7 +10,7 @@ use taffy::style::Overflow;
pub trait Styled: Sized {
fn style(&mut self) -> &mut StyleRefinement;
- gpui2_macros::style_helpers!();
+ gpui_macros::style_helpers!();
fn z_index(mut self, z_index: u8) -> Self {
self.style().z_index = Some(z_index);
@@ -1,11 +1,9 @@
-use gpui2::{actions, impl_actions};
-use gpui2_macros::register_action;
+use gpui::{actions, impl_actions};
+use gpui_macros::register_action;
use serde_derive::Deserialize;
#[test]
fn test_action_macros() {
- use gpui2 as gpui;
-
actions!(test, [TestAction]);
#[derive(PartialEq, Clone, Deserialize)]
@@ -1,14 +0,0 @@
-[package]
-name = "gpui2_macros"
-version = "0.1.0"
-edition = "2021"
-publish = false
-
-[lib]
-path = "src/gpui2_macros.rs"
-proc-macro = true
-
-[dependencies]
-syn = { version = "1.0.72", features = ["full"] }
-quote = "1.0.9"
-proc-macro2 = "1.0.66"
@@ -1,32 +0,0 @@
-mod derive_into_element;
-mod derive_render;
-mod register_action;
-mod style_helpers;
-mod test;
-
-use proc_macro::TokenStream;
-
-#[proc_macro]
-pub fn register_action(ident: TokenStream) -> TokenStream {
- register_action::register_action_macro(ident)
-}
-
-#[proc_macro_derive(IntoElement)]
-pub fn derive_into_element(input: TokenStream) -> TokenStream {
- derive_into_element::derive_into_element(input)
-}
-
-#[proc_macro_derive(Render)]
-pub fn derive_render(input: TokenStream) -> TokenStream {
- derive_render::derive_render(input)
-}
-
-#[proc_macro]
-pub fn style_helpers(input: TokenStream) -> TokenStream {
- style_helpers::style_helpers(input)
-}
-
-#[proc_macro_attribute]
-pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
- test::test(args, function)
-}
@@ -7,10 +7,8 @@ publish = false
[lib]
path = "src/gpui_macros.rs"
proc-macro = true
-doctest = false
[dependencies]
-lazy_static.workspace = true
-proc-macro2 = "1.0"
-syn = "1.0"
-quote = "1.0"
+syn = { version = "1.0.72", features = ["full"] }
+quote = "1.0.9"
+proc-macro2 = "1.0.66"
@@ -13,7 +13,7 @@ pub fn derive_into_element(input: TokenStream) -> TokenStream {
{
type Element = gpui::Component<Self>;
- fn element_id(&self) -> Option<ElementId> {
+ fn element_id(&self) -> Option<gpui::ElementId> {
None
}
@@ -11,7 +11,7 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
impl #impl_generics gpui::Render for #type_name #type_generics
#where_clause
{
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> impl gpui::Element {
()
}
}
@@ -1,381 +1,32 @@
-use proc_macro::TokenStream;
-use proc_macro2::Ident;
-use quote::{format_ident, quote};
-use std::mem;
-use syn::{
- parse_macro_input, parse_quote, spanned::Spanned as _, AttributeArgs, DeriveInput, FnArg,
- GenericParam, Generics, ItemFn, Lit, Meta, NestedMeta, Type, WhereClause,
-};
-
-#[proc_macro_attribute]
-pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
- let mut namespace = format_ident!("gpui");
-
- let args = syn::parse_macro_input!(args as AttributeArgs);
- let mut max_retries = 0;
- let mut num_iterations = 1;
- let mut starting_seed = 0;
- let mut detect_nondeterminism = false;
- let mut on_failure_fn_name = quote!(None);
-
- for arg in args {
- match arg {
- NestedMeta::Meta(Meta::Path(name))
- if name.get_ident().map_or(false, |n| n == "self") =>
- {
- namespace = format_ident!("crate");
- }
- NestedMeta::Meta(Meta::NameValue(meta)) => {
- let key_name = meta.path.get_ident().map(|i| i.to_string());
- let result = (|| {
- match key_name.as_deref() {
- Some("detect_nondeterminism") => {
- detect_nondeterminism = parse_bool(&meta.lit)?
- }
- Some("retries") => max_retries = parse_int(&meta.lit)?,
- Some("iterations") => num_iterations = parse_int(&meta.lit)?,
- Some("seed") => starting_seed = parse_int(&meta.lit)?,
- Some("on_failure") => {
- if let Lit::Str(name) = meta.lit {
- let mut path = syn::Path {
- leading_colon: None,
- segments: Default::default(),
- };
- for part in name.value().split("::") {
- path.segments.push(Ident::new(part, name.span()).into());
- }
- on_failure_fn_name = quote!(Some(#path));
- } else {
- return Err(TokenStream::from(
- syn::Error::new(
- meta.lit.span(),
- "on_failure argument must be a string",
- )
- .into_compile_error(),
- ));
- }
- }
- _ => {
- return Err(TokenStream::from(
- syn::Error::new(meta.path.span(), "invalid argument")
- .into_compile_error(),
- ))
- }
- }
- Ok(())
- })();
-
- if let Err(tokens) = result {
- return tokens;
- }
- }
- other => {
- return TokenStream::from(
- syn::Error::new_spanned(other, "invalid argument").into_compile_error(),
- )
- }
- }
- }
-
- let mut inner_fn = parse_macro_input!(function as ItemFn);
- if max_retries > 0 && num_iterations > 1 {
- return TokenStream::from(
- syn::Error::new_spanned(inner_fn, "retries and randomized iterations can't be mixed")
- .into_compile_error(),
- );
- }
- let inner_fn_attributes = mem::take(&mut inner_fn.attrs);
- let inner_fn_name = format_ident!("_{}", inner_fn.sig.ident);
- let outer_fn_name = mem::replace(&mut inner_fn.sig.ident, inner_fn_name.clone());
-
- let mut outer_fn: ItemFn = if inner_fn.sig.asyncness.is_some() {
- // Pass to the test function the number of app contexts that it needs,
- // based on its parameter list.
- let mut cx_vars = proc_macro2::TokenStream::new();
- let mut cx_teardowns = proc_macro2::TokenStream::new();
- let mut inner_fn_args = proc_macro2::TokenStream::new();
- for (ix, arg) in inner_fn.sig.inputs.iter().enumerate() {
- if let FnArg::Typed(arg) = arg {
- if let Type::Path(ty) = &*arg.ty {
- let last_segment = ty.path.segments.last();
- match last_segment.map(|s| s.ident.to_string()).as_deref() {
- Some("StdRng") => {
- inner_fn_args.extend(quote!(rand::SeedableRng::seed_from_u64(seed),));
- continue;
- }
- Some("Arc") => {
- if let syn::PathArguments::AngleBracketed(args) =
- &last_segment.unwrap().arguments
- {
- if let Some(syn::GenericArgument::Type(syn::Type::Path(ty))) =
- args.args.last()
- {
- let last_segment = ty.path.segments.last();
- if let Some("Deterministic") =
- last_segment.map(|s| s.ident.to_string()).as_deref()
- {
- inner_fn_args.extend(quote!(deterministic.clone(),));
- continue;
- }
- }
- }
- }
- _ => {}
- }
- } else if let Type::Reference(ty) = &*arg.ty {
- if let Type::Path(ty) = &*ty.elem {
- let last_segment = ty.path.segments.last();
- if let Some("TestAppContext") =
- last_segment.map(|s| s.ident.to_string()).as_deref()
- {
- let first_entity_id = ix * 100_000;
- let cx_varname = format_ident!("cx_{}", ix);
- cx_vars.extend(quote!(
- let mut #cx_varname = #namespace::TestAppContext::new(
- foreground_platform.clone(),
- cx.platform().clone(),
- deterministic.build_foreground(#ix),
- deterministic.build_background(),
- cx.font_cache().clone(),
- cx.leak_detector(),
- #first_entity_id,
- stringify!(#outer_fn_name).to_string(),
- );
- ));
- cx_teardowns.extend(quote!(
- #cx_varname.remove_all_windows();
- deterministic.run_until_parked();
- #cx_varname.update(|cx| cx.clear_globals());
- ));
- inner_fn_args.extend(quote!(&mut #cx_varname,));
- continue;
- }
- }
- }
- }
-
- return TokenStream::from(
- syn::Error::new_spanned(arg, "invalid argument").into_compile_error(),
- );
- }
-
- parse_quote! {
- #[test]
- fn #outer_fn_name() {
- #inner_fn
-
- #namespace::test::run_test(
- #num_iterations as u64,
- #starting_seed as u64,
- #max_retries,
- #detect_nondeterminism,
- &mut |cx, foreground_platform, deterministic, seed| {
- // some of the macro contents do not use all variables, silence the warnings
- let _ = (&cx, &foreground_platform, &deterministic, &seed);
- #cx_vars
- cx.foreground().run(#inner_fn_name(#inner_fn_args));
- #cx_teardowns
- },
- #on_failure_fn_name,
- stringify!(#outer_fn_name).to_string(),
- );
- }
- }
- } else {
- // Pass to the test function the number of app contexts that it needs,
- // based on its parameter list.
- let mut cx_vars = proc_macro2::TokenStream::new();
- let mut cx_teardowns = proc_macro2::TokenStream::new();
- let mut inner_fn_args = proc_macro2::TokenStream::new();
- for (ix, arg) in inner_fn.sig.inputs.iter().enumerate() {
- if let FnArg::Typed(arg) = arg {
- if let Type::Path(ty) = &*arg.ty {
- let last_segment = ty.path.segments.last();
-
- if let Some("StdRng") = last_segment.map(|s| s.ident.to_string()).as_deref() {
- inner_fn_args.extend(quote!(rand::SeedableRng::seed_from_u64(seed),));
- continue;
- }
- } else if let Type::Reference(ty) = &*arg.ty {
- if let Type::Path(ty) = &*ty.elem {
- let last_segment = ty.path.segments.last();
- match last_segment.map(|s| s.ident.to_string()).as_deref() {
- Some("AppContext") => {
- inner_fn_args.extend(quote!(cx,));
- continue;
- }
- Some("TestAppContext") => {
- let first_entity_id = ix * 100_000;
- let cx_varname = format_ident!("cx_{}", ix);
- cx_vars.extend(quote!(
- let mut #cx_varname = #namespace::TestAppContext::new(
- foreground_platform.clone(),
- cx.platform().clone(),
- deterministic.build_foreground(#ix),
- deterministic.build_background(),
- cx.font_cache().clone(),
- cx.leak_detector(),
- #first_entity_id,
- stringify!(#outer_fn_name).to_string(),
- );
- ));
- cx_teardowns.extend(quote!(
- #cx_varname.remove_all_windows();
- deterministic.run_until_parked();
- #cx_varname.update(|cx| cx.clear_globals());
- ));
- inner_fn_args.extend(quote!(&mut #cx_varname,));
- continue;
- }
- _ => {}
- }
- }
- }
- }
-
- return TokenStream::from(
- syn::Error::new_spanned(arg, "invalid argument").into_compile_error(),
- );
- }
-
- parse_quote! {
- #[test]
- fn #outer_fn_name() {
- #inner_fn
+mod derive_into_element;
+mod derive_render;
+mod register_action;
+mod style_helpers;
+mod test;
- #namespace::test::run_test(
- #num_iterations as u64,
- #starting_seed as u64,
- #max_retries,
- #detect_nondeterminism,
- &mut |cx, foreground_platform, deterministic, seed| {
- // some of the macro contents do not use all variables, silence the warnings
- let _ = (&cx, &foreground_platform, &deterministic, &seed);
- #cx_vars
- #inner_fn_name(#inner_fn_args);
- #cx_teardowns
- },
- #on_failure_fn_name,
- stringify!(#outer_fn_name).to_string(),
- );
- }
- }
- };
- outer_fn.attrs.extend(inner_fn_attributes);
+use proc_macro::TokenStream;
- TokenStream::from(quote!(#outer_fn))
+#[proc_macro]
+pub fn register_action(ident: TokenStream) -> TokenStream {
+ register_action::register_action_macro(ident)
}
-fn parse_int(literal: &Lit) -> Result<usize, TokenStream> {
- let result = if let Lit::Int(int) = &literal {
- int.base10_parse()
- } else {
- Err(syn::Error::new(literal.span(), "must be an integer"))
- };
-
- result.map_err(|err| TokenStream::from(err.into_compile_error()))
+#[proc_macro_derive(IntoElement)]
+pub fn derive_into_element(input: TokenStream) -> TokenStream {
+ derive_into_element::derive_into_element(input)
}
-fn parse_bool(literal: &Lit) -> Result<bool, TokenStream> {
- let result = if let Lit::Bool(result) = &literal {
- Ok(result.value)
- } else {
- Err(syn::Error::new(literal.span(), "must be a boolean"))
- };
-
- result.map_err(|err| TokenStream::from(err.into_compile_error()))
+#[proc_macro_derive(Render)]
+pub fn derive_render(input: TokenStream) -> TokenStream {
+ derive_render::derive_render(input)
}
-#[proc_macro_derive(Element)]
-pub fn element_derive(input: TokenStream) -> TokenStream {
- let ast = parse_macro_input!(input as DeriveInput);
- let type_name = ast.ident;
-
- let placeholder_view_generics: Generics = parse_quote! { <V: 'static> };
- let placeholder_view_type_name: Ident = parse_quote! { V };
- let view_type_name: Ident;
- let impl_generics: syn::ImplGenerics<'_>;
- let type_generics: Option<syn::TypeGenerics<'_>>;
- let where_clause: Option<&'_ WhereClause>;
-
- match ast.generics.params.iter().find_map(|param| {
- if let GenericParam::Type(type_param) = param {
- Some(type_param.ident.clone())
- } else {
- None
- }
- }) {
- Some(type_name) => {
- view_type_name = type_name;
- let generics = ast.generics.split_for_impl();
- impl_generics = generics.0;
- type_generics = Some(generics.1);
- where_clause = generics.2;
- }
- _ => {
- view_type_name = placeholder_view_type_name;
- let generics = placeholder_view_generics.split_for_impl();
- impl_generics = generics.0;
- type_generics = None;
- where_clause = generics.2;
- }
- }
-
- let gen = quote! {
- impl #impl_generics Element<#view_type_name> for #type_name #type_generics
- #where_clause
- {
-
- type LayoutState = gpui::elements::AnyElement<V>;
- type PaintState = ();
-
- fn layout(
- &mut self,
- constraint: gpui::SizeConstraint,
- view: &mut V,
- cx: &mut gpui::ViewContext<V>,
- ) -> (gpui::geometry::vector::Vector2F, gpui::elements::AnyElement<V>) {
- let mut element = self.render(view, cx).into_any();
- let size = element.layout(constraint, view, cx);
- (size, element)
- }
-
- fn paint(
- &mut self,
- bounds: gpui::geometry::rect::RectF,
- visible_bounds: gpui::geometry::rect::RectF,
- element: &mut gpui::elements::AnyElement<V>,
- view: &mut V,
- cx: &mut gpui::ViewContext<V>,
- ) {
- element.paint(bounds.origin(), visible_bounds, view, cx);
- }
-
- fn rect_for_text_range(
- &self,
- range_utf16: std::ops::Range<usize>,
- _: gpui::geometry::rect::RectF,
- _: gpui::geometry::rect::RectF,
- element: &gpui::elements::AnyElement<V>,
- _: &(),
- view: &V,
- cx: &gpui::ViewContext<V>,
- ) -> Option<gpui::geometry::rect::RectF> {
- element.rect_for_text_range(range_utf16, view, cx)
- }
-
- fn debug(
- &self,
- _: gpui::geometry::rect::RectF,
- element: &gpui::elements::AnyElement<V>,
- _: &(),
- view: &V,
- cx: &gpui::ViewContext<V>,
- ) -> gpui::json::Value {
- element.debug(view, cx)
- }
- }
- };
+#[proc_macro]
+pub fn style_helpers(input: TokenStream) -> TokenStream {
+ style_helpers::style_helpers(input)
+}
- gen.into()
+#[proc_macro_attribute]
+pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
+ test::test(args, function)
}
@@ -342,7 +342,7 @@ impl Peer {
pub fn add_test_connection(
self: &Arc<Self>,
connection: Connection,
- executor: Arc<gpui::executor::Background>,
+ executor: gpui::BackgroundExecutor,
) -> (
ConnectionId,
impl Future<Output = anyhow::Result<()>> + Send,
@@ -559,7 +559,6 @@ mod tests {
use async_tungstenite::tungstenite::Message as WebSocketMessage;
use gpui::TestAppContext;
- #[ctor::ctor]
fn init_logger() {
if std::env::var("RUST_LOG").is_ok() {
env_logger::init();
@@ -568,7 +567,9 @@ mod tests {
#[gpui::test(iterations = 50)]
async fn test_request_response(cx: &mut TestAppContext) {
- let executor = cx.foreground();
+ init_logger();
+
+ let executor = cx.executor();
// create 2 clients connected to 1 server
let server = Peer::new(0);
@@ -576,18 +577,18 @@ mod tests {
let client2 = Peer::new(0);
let (client1_to_server_conn, server_to_client_1_conn, _kill) =
- Connection::in_memory(cx.background());
+ Connection::in_memory(cx.executor());
let (client1_conn_id, io_task1, client1_incoming) =
- client1.add_test_connection(client1_to_server_conn, cx.background());
+ client1.add_test_connection(client1_to_server_conn, cx.executor());
let (_, io_task2, server_incoming1) =
- server.add_test_connection(server_to_client_1_conn, cx.background());
+ server.add_test_connection(server_to_client_1_conn, cx.executor());
let (client2_to_server_conn, server_to_client_2_conn, _kill) =
- Connection::in_memory(cx.background());
+ Connection::in_memory(cx.executor());
let (client2_conn_id, io_task3, client2_incoming) =
- client2.add_test_connection(client2_to_server_conn, cx.background());
+ client2.add_test_connection(client2_to_server_conn, cx.executor());
let (_, io_task4, server_incoming2) =
- server.add_test_connection(server_to_client_2_conn, cx.background());
+ server.add_test_connection(server_to_client_2_conn, cx.executor());
executor.spawn(io_task1).detach();
executor.spawn(io_task2).detach();
@@ -664,25 +665,25 @@ mod tests {
#[gpui::test(iterations = 50)]
async fn test_order_of_response_and_incoming(cx: &mut TestAppContext) {
- let executor = cx.foreground();
+ let executor = cx.executor();
let server = Peer::new(0);
let client = Peer::new(0);
let (client_to_server_conn, server_to_client_conn, _kill) =
- Connection::in_memory(cx.background());
+ Connection::in_memory(executor.clone());
let (client_to_server_conn_id, io_task1, mut client_incoming) =
- client.add_test_connection(client_to_server_conn, cx.background());
+ client.add_test_connection(client_to_server_conn, executor.clone());
+
let (server_to_client_conn_id, io_task2, mut server_incoming) =
- server.add_test_connection(server_to_client_conn, cx.background());
+ server.add_test_connection(server_to_client_conn, executor.clone());
executor.spawn(io_task1).detach();
executor.spawn(io_task2).detach();
executor
.spawn(async move {
- let request = server_incoming
- .next()
- .await
+ let future = server_incoming.next().await;
+ let request = future
.unwrap()
.into_any()
.downcast::<TypedEnvelope<proto::Ping>>()
@@ -762,16 +763,16 @@ mod tests {
#[gpui::test(iterations = 50)]
async fn test_dropping_request_before_completion(cx: &mut TestAppContext) {
- let executor = cx.foreground();
+ let executor = cx.executor();
let server = Peer::new(0);
let client = Peer::new(0);
let (client_to_server_conn, server_to_client_conn, _kill) =
- Connection::in_memory(cx.background());
+ Connection::in_memory(cx.executor());
let (client_to_server_conn_id, io_task1, mut client_incoming) =
- client.add_test_connection(client_to_server_conn, cx.background());
+ client.add_test_connection(client_to_server_conn, cx.executor());
let (server_to_client_conn_id, io_task2, mut server_incoming) =
- server.add_test_connection(server_to_client_conn, cx.background());
+ server.add_test_connection(server_to_client_conn, cx.executor());
executor.spawn(io_task1).detach();
executor.spawn(io_task2).detach();
@@ -858,7 +859,7 @@ mod tests {
.detach();
// Allow the request to make some progress before dropping it.
- cx.background().simulate_random_delay().await;
+ cx.executor().simulate_random_delay().await;
drop(request1_task);
request2_task.await;
@@ -874,13 +875,13 @@ mod tests {
#[gpui::test(iterations = 50)]
async fn test_disconnect(cx: &mut TestAppContext) {
- let executor = cx.foreground();
+ let executor = cx.executor();
- let (client_conn, mut server_conn, _kill) = Connection::in_memory(cx.background());
+ let (client_conn, mut server_conn, _kill) = Connection::in_memory(executor.clone());
let client = Peer::new(0);
let (connection_id, io_handler, mut incoming) =
- client.add_test_connection(client_conn, cx.background());
+ client.add_test_connection(client_conn, executor.clone());
let (io_ended_tx, io_ended_rx) = oneshot::channel();
executor
@@ -910,12 +911,12 @@ mod tests {
#[gpui::test(iterations = 50)]
async fn test_io_error(cx: &mut TestAppContext) {
- let executor = cx.foreground();
- let (client_conn, mut server_conn, _kill) = Connection::in_memory(cx.background());
+ let executor = cx.executor();
+ let (client_conn, mut server_conn, _kill) = Connection::in_memory(executor.clone());
let client = Peer::new(0);
let (connection_id, io_handler, mut incoming) =
- client.add_test_connection(client_conn, cx.background());
+ client.add_test_connection(client_conn, executor.clone());
executor.spawn(io_handler).detach();
executor
.spawn(async move { incoming.next().await })
@@ -31,6 +31,7 @@ smallvec.workspace = true
story = { path = "../story" }
theme = { path = "../theme" }
menu = { path = "../menu" }
+ui = { path = "../ui", features = ["stories"] }
util = { path = "../util" }
picker = { path = "../picker" }
@@ -1,9 +1,8 @@
use gpui::{
- div, AnyElement, Element, ElementId, IntoElement, ParentElement, RenderOnce, Styled,
+ div, AnyElement, Element, IntoElement, ParentElement, RenderOnce, Styled,
WindowContext,
};
use smallvec::SmallVec;
-
use crate::prelude::*;
use crate::v_stack;
@@ -1,13 +0,0 @@
-[package]
-name = "xtask"
-version = "0.1.0"
-edition = "2021"
-publish = false
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-anyhow = "1.0"
-clap = {version = "4.0", features = ["derive"]}
-theme = {path = "../theme"}
-serde_json.workspace = true
-schemars.workspace = true
@@ -1,23 +0,0 @@
-use clap::{Parser, Subcommand};
-use std::path::PathBuf;
-/// Common utilities for Zed developers.
-// For more information, see [matklad's repository README](https://github.com/matklad/cargo-xtask/)
-#[derive(Parser)]
-#[command(author, version, about, long_about = None)]
-#[command(propagate_version = true)]
-pub struct Cli {
- #[command(subcommand)]
- pub command: Commands,
-}
-
-/// Command to run.
-#[derive(Subcommand)]
-pub enum Commands {
- /// Builds theme types for interop with Typescript.
- BuildThemeTypes {
- #[clap(short, long, default_value = "schemas")]
- out_dir: PathBuf,
- #[clap(short, long, default_value = "theme.json")]
- file_name: PathBuf,
- },
-}
@@ -1,29 +0,0 @@
-mod cli;
-
-use std::path::PathBuf;
-
-use anyhow::Result;
-use clap::Parser;
-use schemars::schema_for;
-use theme::Theme;
-
-fn build_themes(out_dir: PathBuf, file_name: PathBuf) -> Result<()> {
- let theme = schema_for!(Theme);
- let output = serde_json::to_string_pretty(&theme)?;
-
- std::fs::create_dir(&out_dir)?;
-
- let mut file_path = out_dir;
- file_path.push(file_name);
-
- std::fs::write(file_path, output)?;
-
- Ok(())
-}
-
-fn main() -> Result<()> {
- let args = cli::Cli::parse();
- match args.command {
- cli::Commands::BuildThemeTypes { out_dir, file_name } => build_themes(out_dir, file_name),
- }
-}