From d80959d64e7e2b13cc33e3ec6114fc568982c0fc Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 23 Jan 2024 21:29:12 -0800 Subject: [PATCH 1/5] Add module documentation to GPUI and make gpui.rs example compile --- crates/gpui/src/color.rs | 5 ++- crates/gpui/src/elements/div.rs | 7 ---- crates/gpui/src/elements/text.rs | 12 +++++++ crates/gpui/src/gpui.rs | 62 +++++++++++++++++++++++--------- 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/crates/gpui/src/color.rs b/crates/gpui/src/color.rs index dadc3d5ad3..caf7cddf69 100644 --- a/crates/gpui/src/color.rs +++ b/crates/gpui/src/color.rs @@ -3,11 +3,11 @@ use serde::de::{self, Deserialize, Deserializer, Visitor}; use std::fmt; /// Convert an RGB hex color code number to a color type -pub fn rgb>(hex: u32) -> C { +pub fn rgb(hex: u32) -> Rgba { let r = ((hex >> 16) & 0xFF) as f32 / 255.0; let g = ((hex >> 8) & 0xFF) as f32 / 255.0; let b = (hex & 0xFF) as f32 / 255.0; - Rgba { r, g, b, a: 1.0 }.into() + Rgba { r, g, b, a: 1.0 } } /// Convert an RGBA hex color code number to [`Rgba`] @@ -40,7 +40,6 @@ impl fmt::Debug for Rgba { impl Rgba { /// Create a new [`Rgba`] color by blending this and another color together - /// TODO!(docs): find the source for this algorithm pub fn blend(&self, other: Rgba) -> Self { if other.a >= 1.0 { other diff --git a/crates/gpui/src/elements/div.rs b/crates/gpui/src/elements/div.rs index 4a951fb48d..a0bbf6fc79 100644 --- a/crates/gpui/src/elements/div.rs +++ b/crates/gpui/src/elements/div.rs @@ -14,13 +14,6 @@ //! as several associated traits. Together, these provide the full suite of Dom-like events //! and Tailwind-like styling that you can use to build your own custom elements. Div is //! constructed by combining these two systems into an all-in-one element. -//! -//! # Capturing and bubbling -//! -//! Note that while event dispatch in GPUI uses similar names and concepts to the web -//! even API, the details are very different. See the documentation in [TODO!(docs) -//! DOCUMENT EVENT DISPATCH SOMEWHERE IN WINDOW CONTEXT] for more details -//! use crate::{ point, px, size, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, Bounds, diff --git a/crates/gpui/src/elements/text.rs b/crates/gpui/src/elements/text.rs index 13fc620076..2b5bf9166e 100644 --- a/crates/gpui/src/elements/text.rs +++ b/crates/gpui/src/elements/text.rs @@ -46,6 +46,18 @@ impl IntoElement for &'static str { } } +impl IntoElement for String { + type Element = SharedString; + + fn element_id(&self) -> Option { + None + } + + fn into_element(self) -> Self::Element { + self.into() + } +} + impl Element for SharedString { type State = TextState; diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 8ecfd8ad6d..5e5618721b 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -1,30 +1,60 @@ //! # Welcome to GPUI! //! //! GPUI is a hybrid immediate and retained mode, GPU accelerated, UI framework -//! for Rust, designed to support a wide variety of applications. GPUI is currently -//! being actively developed and improved for the [Zed code editor](https://zed.dev/), and new versions -//! will have breaking changes. You'll probably need to use the latest stable version -//! of rust to use GPUI. +//! for Rust, designed to support a wide variety of applications. //! -//! # Getting started with GPUI +//! ## Getting Started //! -//! TODO!(docs): Write a code sample showing how to create a window and render a simple -//! div +//! GPUI is still in active development as we work on the Zed code editor and isn't yet on crates.io. +//! You'll also need to use the latest version of stable rust. Add the following to your Cargo.toml: //! -//! # Drawing interesting things +//! gpui = { git = "https://github.com/zed-industries/zed" } //! -//! TODO!(docs): Expand demo to show how to draw a more interesting scene, with -//! a counter to store state and a button to increment it. +//! Everything in GPUI starts with an [`App`]. You can create one with [`App::new`], and +//! kick off your application by passing a callback to [`App::run`]. Inside this callback, +//! you can create a new window with [`AppContext::open_window`], and register your first root +//! view. See [gpui.rs](https://www.gpui.rs/) for a complete example. //! -//! # Interacting with your application state +//! ## The Big Picture //! -//! TODO!(docs): Expand demo to show GPUI entity interactions, like subscriptions and entities -//! maybe make a network request to show async stuff? +//! GPUI offers three different [registers](https://en.wikipedia.org/wiki/Register_(sociolinguistics)) depending on your needs: //! -//! # Conclusion +//! - State management and communication with Models. Whenever you need to store application state +//! that communicates between different parts of your application, you'll want to use GPUI's +//! models. Models are owned by GPUI and are only accessible through an owned smart pointer +//! similar to an [`Rc`]. See the [`app::model_context`] module for more information. //! -//! TODO!(docs): Wrap up with a conclusion and links to other places? Zed / GPUI website? -//! Discord for chatting about it? Other tutorials or references? +//! - High level, declarative UI with Views. All UI in GPUI starts with a View. A view is simply +//! a model that can be rendered, via the [`Render`] trait. At the start of each frame, GPUI +//! will call this render method on the root view of a given window. Views build a tree of +//! `elements`, lay them out and style them with a tailwind-style API, and then give them to +//! GPUI to turn into pixels. See the [`div`] element for an all purpose swiss-army knife of +//! rendering. +//! +//! - Low level, imperative UI with Elements. Elements are the building blocks of UI in GPUI, and they +//! provide a nice wrapper around an imperative API that provides as much flexibility and control as +//! you need. Elements have total control over how they and their child elements are rendered and and +//! can be used for making efficient views into large lists, implement custom layouting for a code editor, +//! and anything else you can think of. See the [`element`] module for more information. +//! +//! Each of these registers has one or more corresponding contexts that can be accessed from all GPUI services. +//! This context is your main interface to GPUI, and is used extensively throughout the framework. +//! +//! ## Other Resources +//! +//! In addition to the systems above, GPUI provides a range of smaller services that are useful for building +//! complex applications: +//! +//! - Actions are user-defined structs that are used for converting keystrokes into logical operations in your UI. +//! Use this for implementing keyboard shortcuts, such as cmd-q. See the [`action`] module for more information. +//! - Platform services, such as `quit the app` or `open a URL` are available as methods on the [`app::AppContext`]. +//! - An async executor that is integrated with the platform's event loop. See the [`executor`] module for more information., +//! - The [gpui::test] macro provides a convenient way to write tests for your GPUI applications. Tests also have their +//! own kind of context, a [`TestAppContext`] which provides ways of simulating common platform input. See [`app::test_context`] +//! and [`test`] modules for more details. +//! +//! Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack. +//! We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). #![deny(missing_docs)] #![allow(clippy::type_complexity)] From ce7cd5a077e4cadedae6e3c889035a61566539cf Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 23 Jan 2024 21:35:01 -0800 Subject: [PATCH 2/5] Copy GPUI documentation to README --- crates/gpui/README.md | 42 +++++++++++++++++++++++++++++++++++++++-- crates/gpui/src/gpui.rs | 9 ++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/crates/gpui/README.md b/crates/gpui/README.md index e145946024..cb275eb944 100644 --- a/crates/gpui/README.md +++ b/crates/gpui/README.md @@ -1,3 +1,41 @@ -# GPUI +# Welcome to GPUI! + +GPUI is a hybrid immediate and retained mode, GPU accelerated, UI framework +for Rust, designed to support a wide variety of applications. + +## Getting Started + +GPUI is still in active development as we work on the Zed code editor and isn't yet on crates.io. You'll also need to use the latest version of stable rust and be on macOS. Add the following to your Cargo.toml: + +``` +gpui = { git = "https://github.com/zed-industries/zed" } +``` + +Everything in GPUI starts with an `App`. You can create one with `App::new()`, and kick off your application by passing a callback to `App::run()`. Inside this callback, you can create a new window with `AppContext::open_window()`, and register your first root view. See [gpui.rs](https://www.gpui.rs/) for a complete example. + +## The Big Picture + +GPUI offers three different registers(https://en.wikipedia.org/wiki/Register_(sociolinguistics)) depending on your needs: + +- State management and communication with Models. Whenever you need to store application state that communicates between different parts of your application, you'll want to use GPUI's models. Models are owned by GPUI and are only accessible through an owned smart pointer similar to an `Rc`. See the `app::model_context` module for more information. + +- High level, declarative UI with Views. All UI in GPUI starts with a View. A view is simply a model that can be rendered, via the `Render` trait. At the start of each frame, GPUI will call this render method on the root view of a given window. Views build a tree of `elements`, lay them out and style them with a tailwind-style API, and then give them to GPUI to turn into pixels. See the `div` element for an all purpose swiss-army knife of rendering. + +- Low level, imperative UI with Elements. Elements are the building blocks of UI in GPUI, and they provide a nice wrapper around an imperative API that provides as much flexibility and control as you need. Elements have total control over how they and their child elements are rendered and and can be used for making efficient views into large lists, implement custom layouting for a code editor, and anything else you can think of. See the `element` module for more information. + +Each of these registers has one or more corresponding contexts that can be accessed from all GPUI services. This context is your main interface to GPUI, and is used extensively throughout the framework. + +## Other Resources + +In addition to the systems above, GPUI provides a range of smaller services that are useful for building complex applications: + +- Actions are user-defined structs that are used for converting keystrokes into logical operations in your UI. Use this for implementing keyboard shortcuts, such as cmd-q. See the `action` module for more information. + +- Platform services, such as `quit the app` or `open a URL` are available as methods on the `app::AppContext`. + +- An async executor that is integrated with the platform's event loop. See the `executor` module for more information., + +- The `[gpui::test]` macro provides a convenient way to write tests for your GPUI applications. Tests also have their own kind of context, a `TestAppContext` which provides ways of simulating common platform input. See `app::test_context` and `test` modules for more details. + +Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack. We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). -A fast, productive UI framework from the creators of [https://zed.dev]. diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 5e5618721b..f821ba34ef 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -6,9 +6,12 @@ //! ## Getting Started //! //! GPUI is still in active development as we work on the Zed code editor and isn't yet on crates.io. -//! You'll also need to use the latest version of stable rust. Add the following to your Cargo.toml: +//! You'll also need to use the latest version of stable rust and be on macOS. Add the following to your +//! Cargo.toml: //! +//! ``` //! gpui = { git = "https://github.com/zed-industries/zed" } +//! ``` //! //! Everything in GPUI starts with an [`App`]. You can create one with [`App::new`], and //! kick off your application by passing a callback to [`App::run`]. Inside this callback, @@ -28,8 +31,8 @@ //! a model that can be rendered, via the [`Render`] trait. At the start of each frame, GPUI //! will call this render method on the root view of a given window. Views build a tree of //! `elements`, lay them out and style them with a tailwind-style API, and then give them to -//! GPUI to turn into pixels. See the [`div`] element for an all purpose swiss-army knife of -//! rendering. +//! GPUI to turn into pixels. See the [`elements::Div`] element for an all purpose swiss-army +//! knife for UI. //! //! - Low level, imperative UI with Elements. Elements are the building blocks of UI in GPUI, and they //! provide a nice wrapper around an imperative API that provides as much flexibility and control as From 1facc9fc116e3aeeacfb7ce2b3ef252eb79554cc Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 23 Jan 2024 21:38:16 -0800 Subject: [PATCH 3/5] Fix test error --- crates/theme/src/styles/colors.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/theme/src/styles/colors.rs b/crates/theme/src/styles/colors.rs index a01e73f5ef..b830d19fee 100644 --- a/crates/theme/src/styles/colors.rs +++ b/crates/theme/src/styles/colors.rs @@ -261,7 +261,7 @@ mod tests { fn override_a_single_theme_color() { let mut colors = ThemeColors::light(); - let magenta: Hsla = gpui::rgb(0xff00ff); + let magenta: Hsla = gpui::rgb(0xff00ff).into(); assert_ne!(colors.text, magenta); @@ -279,8 +279,8 @@ mod tests { fn override_multiple_theme_colors() { let mut colors = ThemeColors::light(); - let magenta: Hsla = gpui::rgb(0xff00ff); - let green: Hsla = gpui::rgb(0x00ff00); + let magenta: Hsla = gpui::rgb(0xff00ff).into(); + let green: Hsla = gpui::rgb(0x00ff00).into(); assert_ne!(colors.text, magenta); assert_ne!(colors.background, green); @@ -305,7 +305,7 @@ mod tests { })) .unwrap(); - assert_eq!(colors.background, Some(gpui::rgb(0xff00ff))); - assert_eq!(colors.text, Some(gpui::rgb(0xff0000))); + assert_eq!(colors.background, Some(gpui::rgb(0xff00ff).into())); + assert_eq!(colors.text, Some(gpui::rgb(0xff0000).into())); } } From fa6acc385f619371c4d8c0faad86ce77094aa44a Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 23 Jan 2024 21:41:06 -0800 Subject: [PATCH 4/5] Add note about discord --- crates/gpui/README.md | 2 +- crates/gpui/src/gpui.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/gpui/README.md b/crates/gpui/README.md index cb275eb944..1ced697986 100644 --- a/crates/gpui/README.md +++ b/crates/gpui/README.md @@ -37,5 +37,5 @@ In addition to the systems above, GPUI provides a range of smaller services that - The `[gpui::test]` macro provides a convenient way to write tests for your GPUI applications. Tests also have their own kind of context, a `TestAppContext` which provides ways of simulating common platform input. See `app::test_context` and `test` modules for more details. -Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack. We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). +Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack or in the [Zed Discord](https://discord.gg/U4qhCEhMXP). We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index f821ba34ef..4a1cf41193 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -56,7 +56,7 @@ //! own kind of context, a [`TestAppContext`] which provides ways of simulating common platform input. See [`app::test_context`] //! and [`test`] modules for more details. //! -//! Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack. +//! Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack or in the [Zed Discord](https://discord.gg/U4qhCEhMXP). //! We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). #![deny(missing_docs)] From ce0ff819f915531d16a319845fd5e01b54062087 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 23 Jan 2024 21:47:44 -0800 Subject: [PATCH 5/5] Fix more tests --- crates/gpui/README.md | 3 +-- crates/gpui/src/gpui.rs | 5 +++-- crates/storybook/src/stories/z_index.rs | 18 +++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/gpui/README.md b/crates/gpui/README.md index 1ced697986..9b087a9752 100644 --- a/crates/gpui/README.md +++ b/crates/gpui/README.md @@ -37,5 +37,4 @@ In addition to the systems above, GPUI provides a range of smaller services that - The `[gpui::test]` macro provides a convenient way to write tests for your GPUI applications. Tests also have their own kind of context, a `TestAppContext` which provides ways of simulating common platform input. See `app::test_context` and `test` modules for more details. -Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack or in the [Zed Discord](https://discord.gg/U4qhCEhMXP). We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). - +Currently, the best way to learn about these APIs is to read the Zed source code, ask us about it at a fireside hack, or drop a question in the [Zed Discord](https://discord.gg/U4qhCEhMXP). We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 4a1cf41193..638e94de39 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -56,8 +56,9 @@ //! own kind of context, a [`TestAppContext`] which provides ways of simulating common platform input. See [`app::test_context`] //! and [`test`] modules for more details. //! -//! Currently, the best way to learn about these APIs is to read the Zed source code or to ask us about it at a fireside hack or in the [Zed Discord](https://discord.gg/U4qhCEhMXP). -//! We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). +//! Currently, the best way to learn about these APIs is to read the Zed source code, ask us about it at a fireside hack, or drop +//! a question in the [Zed Discord](https://discord.gg/U4qhCEhMXP). We're working on improving the documentation, creating more examples, +//! and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). #![deny(missing_docs)] #![allow(clippy::type_complexity)] diff --git a/crates/storybook/src/stories/z_index.rs b/crates/storybook/src/stories/z_index.rs index 63ee1af759..e32e39a2d1 100644 --- a/crates/storybook/src/stories/z_index.rs +++ b/crates/storybook/src/stories/z_index.rs @@ -1,4 +1,4 @@ -use gpui::{px, rgb, Div, Hsla, IntoElement, Render, RenderOnce}; +use gpui::{px, rgb, Div, IntoElement, Render, RenderOnce}; use story::Story; use ui::prelude::*; @@ -51,22 +51,22 @@ trait Styles: Styled + Sized { self.absolute() .w(px(150.)) .h(px(50.)) - .text_color(rgb::(0x000000)) + .text_color(rgb(0x000000)) } fn blue(self) -> Self { - self.bg(rgb::(0xe5e8fc)) + self.bg(rgb(0xe5e8fc)) .border_5() - .border_color(rgb::(0x112382)) + .border_color(rgb(0x112382)) .line_height(px(55.)) // HACK: Simulate `text-align: center`. .pl(px(24.)) } fn red(self) -> Self { - self.bg(rgb::(0xfce5e7)) + self.bg(rgb(0xfce5e7)) .border_5() - .border_color(rgb::(0xe3a1a7)) + .border_color(rgb(0xe3a1a7)) // HACK: Simulate `text-align: center`. .pl(px(8.)) } @@ -92,10 +92,10 @@ impl RenderOnce for ZIndexExample { .left(px(15.)) .w(px(180.)) .h(px(230.)) - .bg(rgb::(0xfcfbe5)) - .text_color(rgb::(0x000000)) + .bg(rgb(0xfcfbe5)) + .text_color(rgb(0x000000)) .border_5() - .border_color(rgb::(0xe3e0a1)) + .border_color(rgb(0xe3e0a1)) .line_height(px(215.)) // HACK: Simulate `text-align: center`. .pl(px(24.))