Detailed changes
@@ -8,13 +8,13 @@
//! # Element Basics
//!
//! Elements are constructed by calling [`Render::render()`] on the root view of the window, which
-//! which recursively constructs the element tree from the current state of the application.
+//! which recursively constructs the element tree from the current state of the application,.
//! These elements are then laid out by Taffy, and painted to the screen according to their own
//! implementation of [`Element::paint()`]. Before the start of the next frame, the entire element
//! tree and any callbacks they have registered with GPUI are dropped and the process repeats.
//!
//! But some state is too simple and voluminous to store in every view that needs it, e.g.
-//! whether a hover has been started or not. For this, GPUI provides the [`Element::State`], type.
+//! whether a hover has been started or not. For this, GPUI provides the [`Element::State`], associated type.
//! If an element returns an [`ElementId`] from [`IntoElement::element_id()`], and that element id
//! appears in the same place relative to other views and ElementIds in the frame, then the previous
//! frame's state will be passed to the element's layout and paint methods.
@@ -30,7 +30,7 @@
//!
//! However, most of the time, you won't need to implement your own elements. GPUI provides a number of
//! elements that should cover most common use cases out of the box and it's recommended that you use those
-//! to construct `components`, using the `RenderOnce` trait and the `#[derive(IntoElement)]` macro. Only implement
+//! to construct `components`, using the [`RenderOnce`] trait and the `#[derive(IntoElement)]` macro. Only implement
//! elements when you need to take manual control of the layout and painting process, such as when using
//! your own custom layout algorithm or rendering a code editor.
@@ -9,11 +9,15 @@ use futures::FutureExt;
use media::core_video::CVImageBuffer;
use util::ResultExt;
+/// A source of image content.
#[derive(Clone, Debug)]
pub enum ImageSource {
/// Image content will be loaded from provided URI at render time.
Uri(SharedUrl),
+ /// Cached image data
Data(Arc<ImageData>),
+ // TODO: move surface definitions into mac platform module
+ /// A CoreVideo image buffer
Surface(CVImageBuffer),
}
@@ -47,12 +51,14 @@ impl From<CVImageBuffer> for ImageSource {
}
}
+/// An image element.
pub struct Img {
interactivity: Interactivity,
source: ImageSource,
grayscale: bool,
}
+/// Create a new image element.
pub fn img(source: impl Into<ImageSource>) -> Img {
Img {
interactivity: Interactivity::default(),
@@ -62,6 +68,7 @@ pub fn img(source: impl Into<ImageSource>) -> Img {
}
impl Img {
+ /// Set the image to be displayed in grayscale.
pub fn grayscale(mut self, grayscale: bool) -> Self {
self.grayscale = grayscale;
self
@@ -1,3 +1,11 @@
+//! A list element that can be used to render a large number of differently sized elements
+//! efficiently. Clients of this API need to ensure that elements outside of the scrolled
+//! area do not change their height for this element to function correctly. In order to minimize
+//! re-renders, this element's state is stored intrusively on your own views, so that your code
+//! can coordinate directly with the list element's cached state.
+//!
+//! If all of your elements are the same height, see [`UniformList`] for a simpler API
+
use crate::{
point, px, AnyElement, AvailableSpace, BorrowAppContext, BorrowWindow, Bounds, ContentMask,
DispatchPhase, Element, IntoElement, Pixels, Point, ScrollWheelEvent, Size, Style,
@@ -8,6 +16,7 @@ use refineable::Refineable as _;
use std::{cell::RefCell, ops::Range, rc::Rc};
use sum_tree::{Bias, SumTree};
+/// Construct a new list element
pub fn list(state: ListState) -> List {
List {
state,
@@ -15,11 +24,13 @@ pub fn list(state: ListState) -> List {
}
}
+/// A list element
pub struct List {
state: ListState,
style: StyleRefinement,
}
+/// The list state that views must hold on behalf of the list element.
#[derive(Clone)]
pub struct ListState(Rc<RefCell<StateInner>>);
@@ -35,15 +46,24 @@ struct StateInner {
scroll_handler: Option<Box<dyn FnMut(&ListScrollEvent, &mut WindowContext)>>,
}
+/// Whether the list is scrolling from top to bottom or bottom to top.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ListAlignment {
+ /// The list is scrolling from top to bottom, like most lists.
Top,
+ /// The list is scrolling from bottom to top, like a chat log.
Bottom,
}
+/// A scroll event that has been converted to be in terms of the list's items.
pub struct ListScrollEvent {
+ /// The range of items currently visible in the list, after applying the scroll event.
pub visible_range: Range<usize>,
+
+ /// The number of items that are currently visible in the list, after applying the scroll event.
pub count: usize,
+
+ /// Whether the list has been scrolled.
pub is_scrolled: bool,
}
@@ -74,6 +94,11 @@ struct UnrenderedCount(usize);
struct Height(Pixels);
impl ListState {
+ /// Construct a new list state, for storage on a view.
+ ///
+ /// the overdraw parameter controls how much extra space is rendered
+ /// above and below the visible area. This can help ensure that the list
+ /// doesn't flicker or pop in when scrolling.
pub fn new<F>(
element_count: usize,
orientation: ListAlignment,
@@ -111,10 +136,13 @@ impl ListState {
.extend((0..element_count).map(|_| ListItem::Unrendered), &());
}
+ /// The number of items in this list.
pub fn item_count(&self) -> usize {
self.0.borrow().items.summary().count
}
+ /// Register with the list state that the items in `old_range` have been replaced
+ /// by `count` new items that must be recalculated.
pub fn splice(&self, old_range: Range<usize>, count: usize) {
let state = &mut *self.0.borrow_mut();
@@ -141,6 +169,7 @@ impl ListState {
state.items = new_heights;
}
+ /// Set a handler that will be called when the list is scrolled.
pub fn set_scroll_handler(
&self,
handler: impl FnMut(&ListScrollEvent, &mut WindowContext) + 'static,
@@ -148,10 +177,12 @@ impl ListState {
self.0.borrow_mut().scroll_handler = Some(Box::new(handler))
}
+ /// Get the current scroll offset, in terms of the list's items.
pub fn logical_scroll_top(&self) -> ListOffset {
self.0.borrow().logical_scroll_top()
}
+ /// Scroll the list to the given offset
pub fn scroll_to(&self, mut scroll_top: ListOffset) {
let state = &mut *self.0.borrow_mut();
let item_count = state.items.summary().count;
@@ -163,6 +194,7 @@ impl ListState {
state.logical_scroll_top = Some(scroll_top);
}
+ /// Scroll the list to the given item, such that the item is fully visible.
pub fn scroll_to_reveal_item(&self, ix: usize) {
let state = &mut *self.0.borrow_mut();
@@ -193,7 +225,8 @@ impl ListState {
state.logical_scroll_top = Some(scroll_top);
}
- /// Get the bounds for the given item in window coordinates.
+ /// Get the bounds for the given item in window coordinates, if it's
+ /// been rendered.
pub fn bounds_for_item(&self, ix: usize) -> Option<Bounds<Pixels>> {
let state = &*self.0.borrow();
@@ -310,9 +343,13 @@ impl std::fmt::Debug for ListItem {
}
}
+/// An offset into the list's items, in terms of the item index and the number
+/// of pixels off the top left of the item.
#[derive(Debug, Clone, Copy, Default)]
pub struct ListOffset {
+ /// The index of an item in the list
pub item_ix: usize,
+ /// The number of pixels to offset from the item index.
pub offset_in_item: Pixels,
}
@@ -6,10 +6,13 @@ use crate::{
Point, Size, Style, WindowContext,
};
+/// The state that the overlay element uses to track its children.
pub struct OverlayState {
child_layout_ids: SmallVec<[LayoutId; 4]>,
}
+/// An overlay element that can be used to display UI that
+/// floats on top of other UI elements.
pub struct Overlay {
children: SmallVec<[AnyElement; 2]>,
anchor_corner: AnchorCorner,
@@ -191,15 +194,21 @@ enum Axis {
Vertical,
}
+/// Which algorithm to use when fitting the overlay to be inside the window.
#[derive(Copy, Clone, PartialEq)]
pub enum OverlayFitMode {
+ /// Snap the overlay to the window edge
SnapToWindow,
+ /// Switch which corner anchor this overlay is attached to
SwitchAnchor,
}
+/// Which algorithm to use when positioning the overlay.
#[derive(Copy, Clone, PartialEq)]
pub enum OverlayPositionMode {
+ /// Position the overlay relative to the window
Window,
+ /// Position the overlay relative to its parent
Local,
}
@@ -226,11 +235,16 @@ impl OverlayPositionMode {
}
}
+/// Which corner of the overlay should be considered the anchor.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum AnchorCorner {
+ /// The top left corner
TopLeft,
+ /// The top right corner
TopRight,
+ /// The bottom left corner
BottomLeft,
+ /// The bottom right corner
BottomRight,
}
@@ -255,6 +269,7 @@ impl AnchorCorner {
Bounds { origin, size }
}
+ /// Get the point corresponding to this anchor corner in `bounds`.
pub fn corner(&self, bounds: Bounds<Pixels>) -> Point<Pixels> {
match self {
Self::TopLeft => bounds.origin,
@@ -4,11 +4,13 @@ use crate::{
};
use util::ResultExt;
+/// An SVG element.
pub struct Svg {
interactivity: Interactivity,
path: Option<SharedString>,
}
+/// Create a new SVG element.
pub fn svg() -> Svg {
Svg {
interactivity: Interactivity::default(),
@@ -17,6 +19,7 @@ pub fn svg() -> Svg {
}
impl Svg {
+ /// Set the path to the SVG file for this element.
pub fn path(mut self, path: impl Into<SharedString>) -> Self {
self.path = Some(path.into());
self
@@ -87,6 +87,7 @@ pub struct StyledText {
}
impl StyledText {
+ /// Construct a new styled text element from the given string.
pub fn new(text: impl Into<SharedString>) -> Self {
StyledText {
text: text.into(),
@@ -94,6 +95,8 @@ impl StyledText {
}
}
+ /// Set the styling attributes for the given text, as well as
+ /// as any ranges of text that have had their style customized.
pub fn with_highlights(
mut self,
default_style: &TextStyle,
@@ -151,6 +154,7 @@ impl IntoElement for StyledText {
}
}
+#[doc(hidden)]
#[derive(Default, Clone)]
pub struct TextState(Arc<Mutex<Option<TextStateInner>>>);
@@ -290,6 +294,7 @@ impl TextState {
}
}
+/// A text element that can be interacted with.
pub struct InteractiveText {
element_id: ElementId,
text: StyledText,
@@ -305,6 +310,7 @@ struct InteractiveTextClickEvent {
mouse_up_index: usize,
}
+#[doc(hidden)]
pub struct InteractiveTextState {
text_state: TextState,
mouse_down_index: Rc<Cell<Option<usize>>>,
@@ -314,6 +320,7 @@ pub struct InteractiveTextState {
/// InteractiveTest is a wrapper around StyledText that adds mouse interactions.
impl InteractiveText {
+ /// Creates a new InteractiveText from the given text.
pub fn new(id: impl Into<ElementId>, text: StyledText) -> Self {
Self {
element_id: id.into(),
@@ -1,3 +1,9 @@
+//! A scrollable list of elements with uniform height, optimized for large lists.
+//! Rather than use the full taffy layout system, uniform_list simply measures
+//! the first element and then lays out all remaining elements in a line based on that
+//! measurement. This is much faster than the full layout system, but only works for
+//! elements with uniform height.
+
use crate::{
point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Element,
ElementId, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId,
@@ -53,6 +59,7 @@ where
}
}
+/// A list element for efficiently laying out and displaying a list of uniform-height elements.
pub struct UniformList {
id: ElementId,
item_count: usize,
@@ -63,18 +70,22 @@ pub struct UniformList {
scroll_handle: Option<UniformListScrollHandle>,
}
+/// A handle for controlling the scroll position of a uniform list.
+/// This should be stored in your view and passed to the uniform_list on each frame.
#[derive(Clone, Default)]
pub struct UniformListScrollHandle {
deferred_scroll_to_item: Rc<RefCell<Option<usize>>>,
}
impl UniformListScrollHandle {
+ /// Create a new scroll handle to bind to a uniform list.
pub fn new() -> Self {
Self {
deferred_scroll_to_item: Rc::new(RefCell::new(None)),
}
}
+ /// Scroll the list to the given item index.
pub fn scroll_to_item(&mut self, ix: usize) {
self.deferred_scroll_to_item.replace(Some(ix));
}
@@ -86,6 +97,7 @@ impl Styled for UniformList {
}
}
+#[doc(hidden)]
#[derive(Default)]
pub struct UniformListState {
interactive: InteractiveElementState,
@@ -262,6 +274,7 @@ impl IntoElement for UniformList {
}
impl UniformList {
+ /// Selects a specific list item for measurement.
pub fn with_width_from_item(mut self, item_index: Option<usize>) -> Self {
self.item_to_measure_index = item_index.unwrap_or(0);
self
@@ -284,6 +297,7 @@ impl UniformList {
item_to_measure.measure(available_space, cx)
}
+ /// Track and render scroll state of this list with reference to the given scroll handle.
pub fn track_scroll(mut self, handle: UniformListScrollHandle) -> Self {
self.scroll_handle = Some(handle);
self
@@ -21,11 +21,15 @@ use waker_fn::waker_fn;
#[cfg(any(test, feature = "test-support"))]
use rand::rngs::StdRng;
+/// A pointer to the executor that is currently running,
+/// for spawning background tasks.
#[derive(Clone)]
pub struct BackgroundExecutor {
dispatcher: Arc<dyn PlatformDispatcher>,
}
+/// A pointer to the executor that is currently running,
+/// for spawning tasks on the main thread.
#[derive(Clone)]
pub struct ForegroundExecutor {
dispatcher: Arc<dyn PlatformDispatcher>,
@@ -37,11 +41,14 @@ pub struct ForegroundExecutor {
/// It implements [`Future`] so you can `.await` on it.
///
/// If you drop a task it will be cancelled immediately. Calling [`Task::detach`] allows
-/// the task to continue running in the background, but with no way to return a value.
+/// the task to continue running, but with no way to return a value.
#[must_use]
#[derive(Debug)]
pub enum Task<T> {
+ /// A task that is ready to return a value
Ready(Option<T>),
+
+ /// A task that is currently running.
Spawned(async_task::Task<T>),
}
@@ -87,6 +94,8 @@ impl<T> Future for Task<T> {
}
}
+/// A task label is an opaque identifier that you can use to
+/// refer to a task in tests.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct TaskLabel(NonZeroUsize);
@@ -97,6 +106,7 @@ impl Default for TaskLabel {
}
impl TaskLabel {
+ /// Construct a new task label.
pub fn new() -> Self {
static NEXT_TASK_LABEL: AtomicUsize = AtomicUsize::new(1);
Self(NEXT_TASK_LABEL.fetch_add(1, SeqCst).try_into().unwrap())
@@ -363,6 +373,7 @@ impl BackgroundExecutor {
/// ForegroundExecutor runs things on the main thread.
impl ForegroundExecutor {
+ /// Creates a new ForegroundExecutor from the given PlatformDispatcher.
pub fn new(dispatcher: Arc<dyn PlatformDispatcher>) -> Self {
Self {
dispatcher,
@@ -411,13 +422,14 @@ impl<'a> Scope<'a> {
}
}
+ /// Spawn a future into this scope.
pub fn spawn<F>(&mut self, f: F)
where
F: Future<Output = ()> + Send + 'a,
{
let tx = self.tx.clone().unwrap();
- // Safety: The 'a lifetime is guaranteed to outlive any of these futures because
+ // SAFETY: The 'a lifetime is guaranteed to outlive any of these futures because
// dropping this `Scope` blocks until all of the futures have resolved.
let f = unsafe {
mem::transmute::<
@@ -1,3 +1,33 @@
+//! # Welcome to GPUI!
+//!
+//! GPUI is a hybrid immedate 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.
+//!
+//! # Getting started with GPUI
+//!
+//! TODO: Write a code sample showing how to create a window and render a simple
+//! div
+//!
+//! # Drawing interesting things
+//!
+//! TODO: Expand demo to show how to draw a more interesting scene, with
+//! a counter to store state and a button to increment it.
+//!
+//! # Interacting with your application state
+//!
+//! TODO: Expand demo to show GPUI entity interactions, like subscriptions and entities
+//! maybe make a network request to show async stuff?
+//!
+//! # Conclusion
+//!
+//! TODO: Wrap up with a conclusion and links to other places? Zed / GPUI website?
+//! Discord for chatting about it? Other tutorials or references?
+
+#![deny(missing_docs)]
+
#[macro_use]
mod action;
mod app;
@@ -58,10 +88,10 @@ pub use elements::*;
pub use executor::*;
pub use geometry::*;
pub use gpui_macros::{register_action, test, IntoElement, Render};
-pub use image_cache::*;
+use image_cache::*;
pub use input::*;
pub use interactive::*;
-pub use key_dispatch::*;
+use key_dispatch::*;
pub use keymap::*;
pub use platform::*;
pub use refineable::*;
@@ -73,7 +103,7 @@ pub use smol::Timer;
pub use style::*;
pub use styled::*;
pub use subscription::*;
-pub use svg_renderer::*;
+use svg_renderer::*;
pub use taffy::{AvailableSpace, LayoutId};
#[cfg(any(test, feature = "test-support"))]
pub use test::*;
@@ -82,20 +112,23 @@ pub use util::arc_cow::ArcCow;
pub use view::*;
pub use window::*;
-use std::{
- any::{Any, TypeId},
- borrow::BorrowMut,
-};
+use std::{any::Any, borrow::BorrowMut};
use taffy::TaffyLayoutEngine;
+/// The context trait, allows the different contexts in GPUI to be used
+/// interchangeably for certain operations.
pub trait Context {
+ /// The result type for this context, used for async contexts that
+ /// can't hold a direct reference to the application context.
type Result<T>;
+ /// Create a new model in the app context.
fn new_model<T: 'static>(
&mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>;
+ /// Update a model in the app context.
fn update_model<T, R>(
&mut self,
handle: &Model<T>,
@@ -104,6 +137,7 @@ pub trait Context {
where
T: 'static;
+ /// Read a model from the app context.
fn read_model<T, R>(
&self,
handle: &Model<T>,
@@ -112,10 +146,12 @@ pub trait Context {
where
T: 'static;
+ /// Update a window for the given handle.
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T;
+ /// Read a window off of the application context.
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
@@ -125,7 +161,10 @@ pub trait Context {
T: 'static;
}
+/// This trait is used for the different visual contexts in GPUI that
+/// require a window to be present.
pub trait VisualContext: Context {
+ /// Construct a new view in the window referenced by this context.
fn new_view<V>(
&mut self,
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
@@ -133,12 +172,14 @@ pub trait VisualContext: Context {
where
V: 'static + Render;
+ /// Update a view with the given callback
fn update_view<V: 'static, R>(
&mut self,
view: &View<V>,
update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
) -> Self::Result<R>;
+ /// Replace the root view of a window with a new view.
fn replace_root_view<V>(
&mut self,
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
@@ -146,38 +187,47 @@ pub trait VisualContext: Context {
where
V: 'static + Render;
+ /// Focus a view in the window, if it implements the [`FocusableView`] trait.
fn focus_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
where
V: FocusableView;
+ /// Dismiss a view in the window, if it implements the [`ManagedView`] trait.
fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
where
V: ManagedView;
}
+/// A trait that allows models and views to be interchangeable in certain operations
pub trait Entity<T>: Sealed {
+ /// The weak reference type for this entity.
type Weak: 'static;
+ /// The ID for this entity
fn entity_id(&self) -> EntityId;
+
+ /// Downgrade this entity to a weak reference.
fn downgrade(&self) -> Self::Weak;
+
+ /// Upgrade this entity from a weak reference.
fn upgrade_from(weak: &Self::Weak) -> Option<Self>
where
Self: Sized;
}
+/// A trait for tying together the types of a GPUI entity and the events it can
+/// emit.
pub trait EventEmitter<E: Any>: 'static {}
-pub enum GlobalKey {
- Numeric(usize),
- View(EntityId),
- Type(TypeId),
-}
-
+/// A helper trait for auto-implementing certain methods on contexts that
+/// can be used interchangeably.
pub trait BorrowAppContext {
+ /// Run a closure with a text style pushed onto the context.
fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
where
F: FnOnce(&mut Self) -> R;
+ /// Set a global value on the context.
fn set_global<T: 'static>(&mut self, global: T);
}
@@ -204,7 +254,9 @@ where
}
}
+/// A flatten equivalent for anyhow `Result`s.
pub trait Flatten<T> {
+ /// Convert this type into a simple `Result<T>`.
fn flatten(self) -> Result<T>;
}
@@ -11,12 +11,12 @@ use thiserror::Error;
use util::http::{self, HttpClient};
#[derive(PartialEq, Eq, Hash, Clone)]
-pub struct RenderImageParams {
+pub(crate) struct RenderImageParams {
pub(crate) image_id: ImageId,
}
#[derive(Debug, Error, Clone)]
-pub enum Error {
+pub(crate) enum Error {
#[error("http error: {0}")]
Client(#[from] http::Error),
#[error("IO error: {0}")]
@@ -42,7 +42,7 @@ impl From<ImageError> for Error {
}
}
-pub struct ImageCache {
+pub(crate) struct ImageCache {
client: Arc<dyn HttpClient>,
images: Arc<Mutex<HashMap<SharedUrl, FetchImageFuture>>>,
}
@@ -3,20 +3,33 @@ use std::ops::Range;
/// Implement this trait to allow views to handle textual input when implementing an editor, field, etc.
///
-/// Once your view `V` implements this trait, you can use it to construct an [`ElementInputHandler<V>`].
+/// Once your view implements this trait, you can use it to construct an [`ElementInputHandler<V>`].
/// This input handler can then be assigned during paint by calling [`WindowContext::handle_input`].
+///
+/// See [`InputHandler`] for details on how to implement each method.
pub trait ViewInputHandler: 'static + Sized {
+ /// See [`InputHandler::text_for_range`] for details
fn text_for_range(&mut self, range: Range<usize>, cx: &mut ViewContext<Self>)
-> Option<String>;
+
+ /// See [`InputHandler::selected_text_range`] for details
fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
+
+ /// See [`InputHandler::marked_text_range`] for details
fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
+
+ /// See [`InputHandler::unmark_text`] for details
fn unmark_text(&mut self, cx: &mut ViewContext<Self>);
+
+ /// See [`InputHandler::replace_text_in_range`] for details
fn replace_text_in_range(
&mut self,
range: Option<Range<usize>>,
text: &str,
cx: &mut ViewContext<Self>,
);
+
+ /// See [`InputHandler::replace_and_mark_text_in_range`] for details
fn replace_and_mark_text_in_range(
&mut self,
range: Option<Range<usize>>,
@@ -24,6 +37,8 @@ pub trait ViewInputHandler: 'static + Sized {
new_selected_range: Option<Range<usize>>,
cx: &mut ViewContext<Self>,
);
+
+ /// See [`InputHandler::bounds_for_range`] for details
fn bounds_for_range(
&mut self,
range_utf16: Range<usize>,
@@ -4,15 +4,25 @@ use crate::{
use smallvec::SmallVec;
use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
+/// An event from a platform input source.
pub trait InputEvent: Sealed + 'static {
+ /// Convert this event into the platform input enum.
fn to_platform_input(self) -> PlatformInput;
}
+
+/// A key event from the platform.
pub trait KeyEvent: InputEvent {}
+
+/// A mouse event from the platform.
pub trait MouseEvent: InputEvent {}
+/// The key down event equivalent for the platform.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyDownEvent {
+ /// The keystroke that was generated.
pub keystroke: Keystroke,
+
+ /// Whether the key is currently held down.
pub is_held: bool,
}
@@ -24,8 +34,10 @@ impl InputEvent for KeyDownEvent {
}
impl KeyEvent for KeyDownEvent {}
+/// The key up event equivalent for the platform.
#[derive(Clone, Debug)]
pub struct KeyUpEvent {
+ /// The keystroke that was released.
pub keystroke: Keystroke,
}
@@ -37,8 +49,10 @@ impl InputEvent for KeyUpEvent {
}
impl KeyEvent for KeyUpEvent {}
+/// The modifiers changed event equivalent for the platform.
#[derive(Clone, Debug, Default)]
pub struct ModifiersChangedEvent {
+ /// The new state of the modifier keys
pub modifiers: Modifiers,
}
@@ -62,17 +76,28 @@ impl Deref for ModifiersChangedEvent {
/// Based on the winit enum of the same name.
#[derive(Clone, Copy, Debug, Default)]
pub enum TouchPhase {
+ /// The touch started.
Started,
+ /// The touch event is moving.
#[default]
Moved,
+ /// The touch phase has ended
Ended,
}
+/// A mouse down event from the platform
#[derive(Clone, Debug, Default)]
pub struct MouseDownEvent {
+ /// Which mouse button was pressed.
pub button: MouseButton,
+
+ /// The position of the mouse on the window.
pub position: Point<Pixels>,
+
+ /// The modifiers that were held down when the mouse was pressed.
pub modifiers: Modifiers,
+
+ /// The number of times the button has been clicked.
pub click_count: usize,
}
@@ -84,11 +109,19 @@ impl InputEvent for MouseDownEvent {
}
impl MouseEvent for MouseDownEvent {}
+/// A mouse up event from the platform
#[derive(Clone, Debug, Default)]
pub struct MouseUpEvent {
+ /// Which mouse button was released.
pub button: MouseButton,
+
+ /// The position of the mouse on the window.
pub position: Point<Pixels>,
+
+ /// The modifiers that were held down when the mouse was released.
pub modifiers: Modifiers,
+
+ /// The number of times the button has been clicked.
pub click_count: usize,
}
@@ -100,21 +133,34 @@ impl InputEvent for MouseUpEvent {
}
impl MouseEvent for MouseUpEvent {}
+/// A click event, generated when a mouse button is pressed and released.
#[derive(Clone, Debug, Default)]
pub struct ClickEvent {
+ /// The mouse event when the button was pressed.
pub down: MouseDownEvent,
+
+ /// The mouse event when the button was released.
pub up: MouseUpEvent,
}
+/// An enum representing the mouse button that was pressed.
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
pub enum MouseButton {
+ /// The left mouse button.
Left,
+
+ /// The right mouse button.
Right,
+
+ /// The middle mouse button.
Middle,
+
+ /// A navigation button, such as back or forward.
Navigate(NavigationDirection),
}
impl MouseButton {
+ /// Get all the mouse buttons in a list.
pub fn all() -> Vec<Self> {
vec![
MouseButton::Left,
@@ -132,9 +178,13 @@ impl Default for MouseButton {
}
}
+/// A navigation direction, such as back or forward.
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
pub enum NavigationDirection {
+ /// The back button.
Back,
+
+ /// The forward button.
Forward,
}
@@ -144,10 +194,16 @@ impl Default for NavigationDirection {
}
}
+/// A mouse move event from the platform
#[derive(Clone, Debug, Default)]
pub struct MouseMoveEvent {
+ /// The position of the mouse on the window.
pub position: Point<Pixels>,
+
+ /// The mouse button that was pressed, if any.
pub pressed_button: Option<MouseButton>,
+
+ /// The modifiers that were held down when the mouse was moved.
pub modifiers: Modifiers,
}
@@ -160,16 +216,25 @@ impl InputEvent for MouseMoveEvent {
impl MouseEvent for MouseMoveEvent {}
impl MouseMoveEvent {
+ /// Returns true if the left mouse button is currently held down.
pub fn dragging(&self) -> bool {
self.pressed_button == Some(MouseButton::Left)
}
}
+/// A mouse wheel event from the platform
#[derive(Clone, Debug, Default)]
pub struct ScrollWheelEvent {
+ /// The position of the mouse on the window.
pub position: Point<Pixels>,
+
+ /// The change in scroll wheel position for this event.
pub delta: ScrollDelta,
+
+ /// The modifiers that were held down when the mouse was moved.
pub modifiers: Modifiers,
+
+ /// The phase of the touch event.
pub touch_phase: TouchPhase,
}
@@ -189,9 +254,12 @@ impl Deref for ScrollWheelEvent {
}
}
+/// The scroll delta for a scroll wheel event.
#[derive(Clone, Copy, Debug)]
pub enum ScrollDelta {
+ /// An exact scroll delta in pixels.
Pixels(Point<Pixels>),
+ /// An inexact scroll delta in lines.
Lines(Point<f32>),
}
@@ -202,6 +270,7 @@ impl Default for ScrollDelta {
}
impl ScrollDelta {
+ /// Returns true if this is a precise scroll delta in pixels.
pub fn precise(&self) -> bool {
match self {
ScrollDelta::Pixels(_) => true,
@@ -209,6 +278,7 @@ impl ScrollDelta {
}
}
+ /// Converts this scroll event into exact pixels.
pub fn pixel_delta(&self, line_height: Pixels) -> Point<Pixels> {
match self {
ScrollDelta::Pixels(delta) => *delta,
@@ -216,6 +286,7 @@ impl ScrollDelta {
}
}
+ /// Combines two scroll deltas into one.
pub fn coalesce(self, other: ScrollDelta) -> ScrollDelta {
match (self, other) {
(ScrollDelta::Pixels(px_a), ScrollDelta::Pixels(px_b)) => {
@@ -231,10 +302,15 @@ impl ScrollDelta {
}
}
+/// A mouse exit event from the platform, generated when the mouse leaves the window.
+/// The position generated should be just outside of the window's bounds.
#[derive(Clone, Debug, Default)]
pub struct MouseExitEvent {
+ /// The position of the mouse relative to the window.
pub position: Point<Pixels>,
+ /// The mouse button that was pressed, if any.
pub pressed_button: Option<MouseButton>,
+ /// The modifiers that were held down when the mouse was moved.
pub modifiers: Modifiers,
}
@@ -254,10 +330,12 @@ impl Deref for MouseExitEvent {
}
}
+/// A collection of paths from the platform, such as from a file drop.
#[derive(Debug, Clone, Default)]
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
impl ExternalPaths {
+ /// Convert this collection of paths into a slice.
pub fn paths(&self) -> &[PathBuf] {
&self.0
}
@@ -269,18 +347,27 @@ impl Render for ExternalPaths {
}
}
+/// A file drop event from the platform, generated when files are dragged and dropped onto the window.
#[derive(Debug, Clone)]
pub enum FileDropEvent {
+ /// The files have entered the window.
Entered {
+ /// The position of the mouse relative to the window.
position: Point<Pixels>,
+ /// The paths of the files that are being dragged.
paths: ExternalPaths,
},
+ /// The files are being dragged over the window
Pending {
+ /// The position of the mouse relative to the window.
position: Point<Pixels>,
},
+ /// The files have been dropped onto the window.
Submit {
+ /// The position of the mouse relative to the window.
position: Point<Pixels>,
},
+ /// The user has stopped dragging the files over the window.
Exited,
}
@@ -292,40 +379,31 @@ impl InputEvent for FileDropEvent {
}
impl MouseEvent for FileDropEvent {}
+/// An enum corresponding to all kinds of platform input events.
#[derive(Clone, Debug)]
pub enum PlatformInput {
+ /// A key was pressed.
KeyDown(KeyDownEvent),
+ /// A key was released.
KeyUp(KeyUpEvent),
+ /// The keyboard modifiers were changed.
ModifiersChanged(ModifiersChangedEvent),
+ /// The mouse was pressed.
MouseDown(MouseDownEvent),
+ /// The mouse was released.
MouseUp(MouseUpEvent),
+ /// The mouse was moved.
MouseMove(MouseMoveEvent),
+ /// The mouse exited the window.
MouseExited(MouseExitEvent),
+ /// The scroll wheel was used.
ScrollWheel(ScrollWheelEvent),
+ /// Files were dragged and dropped onto the window.
FileDrop(FileDropEvent),
}
impl PlatformInput {
- pub fn position(&self) -> Option<Point<Pixels>> {
- match self {
- PlatformInput::KeyDown { .. } => None,
- PlatformInput::KeyUp { .. } => None,
- PlatformInput::ModifiersChanged { .. } => None,
- PlatformInput::MouseDown(event) => Some(event.position),
- PlatformInput::MouseUp(event) => Some(event.position),
- PlatformInput::MouseMove(event) => Some(event.position),
- PlatformInput::MouseExited(event) => Some(event.position),
- PlatformInput::ScrollWheel(event) => Some(event.position),
- PlatformInput::FileDrop(FileDropEvent::Exited) => None,
- PlatformInput::FileDrop(
- FileDropEvent::Entered { position, .. }
- | FileDropEvent::Pending { position, .. }
- | FileDropEvent::Submit { position, .. },
- ) => Some(*position),
- }
- }
-
- pub fn mouse_event(&self) -> Option<&dyn Any> {
+ pub(crate) fn mouse_event(&self) -> Option<&dyn Any> {
match self {
PlatformInput::KeyDown { .. } => None,
PlatformInput::KeyUp { .. } => None,
@@ -339,7 +417,7 @@ impl PlatformInput {
}
}
- pub fn keyboard_event(&self) -> Option<&dyn Any> {
+ pub(crate) fn keyboard_event(&self) -> Option<&dyn Any> {
match self {
PlatformInput::KeyDown(event) => Some(event),
PlatformInput::KeyUp(event) => Some(event),
@@ -13,7 +13,7 @@ use std::{
};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
-pub struct DispatchNodeId(usize);
+pub(crate) struct DispatchNodeId(usize);
pub(crate) struct DispatchTree {
node_stack: Vec<DispatchNodeId>,
@@ -2,6 +2,7 @@ use crate::{Action, KeyBindingContextPredicate, KeyMatch, Keystroke};
use anyhow::Result;
use smallvec::SmallVec;
+/// A keybinding and it's associated metadata, from the keymap.
pub struct KeyBinding {
pub(crate) action: Box<dyn Action>,
pub(crate) keystrokes: SmallVec<[Keystroke; 2]>,
@@ -19,10 +20,12 @@ impl Clone for KeyBinding {
}
impl KeyBinding {
+ /// Construct a new keybinding from the given data.
pub fn new<A: Action>(keystrokes: &str, action: A, context_predicate: Option<&str>) -> Self {
Self::load(keystrokes, Box::new(action), context_predicate).unwrap()
}
+ /// Load a keybinding from the given raw data.
pub fn load(keystrokes: &str, action: Box<dyn Action>, context: Option<&str>) -> Result<Self> {
let context = if let Some(context) = context {
Some(KeyBindingContextPredicate::parse(context)?)
@@ -42,6 +45,7 @@ impl KeyBinding {
})
}
+ /// Check if the given keystrokes match this binding.
pub fn match_keystrokes(&self, pending_keystrokes: &[Keystroke]) -> KeyMatch {
if self.keystrokes.as_ref().starts_with(pending_keystrokes) {
// If the binding is completed, push it onto the matches list
@@ -55,10 +59,12 @@ impl KeyBinding {
}
}
+ /// Get the keystrokes associated with this binding
pub fn keystrokes(&self) -> &[Keystroke] {
self.keystrokes.as_slice()
}
+ /// Get the action associated with this binding
pub fn action(&self) -> &dyn Action {
self.action.as_ref()
}
@@ -3,6 +3,10 @@ use anyhow::{anyhow, Result};
use smallvec::SmallVec;
use std::fmt;
+/// A datastructure for resolving whether an action should be dispatched
+/// at this point in the element tree. Contains a set of identifiers
+/// and/or key value pairs representing the current context for the
+/// keymap.
#[derive(Clone, Default, Eq, PartialEq, Hash)]
pub struct KeyContext(SmallVec<[ContextEntry; 1]>);
@@ -21,6 +25,11 @@ impl<'a> TryFrom<&'a str> for KeyContext {
}
impl KeyContext {
+ /// Parse a key context from a string.
+ /// The key context format is very simple:
+ /// - either a single identifier, such as `StatusBar`
+ /// - or a key value pair, such as `mode = visible`
+ /// - seperated by whitespace, such as `StatusBar mode = visible`
pub fn parse(source: &str) -> Result<Self> {
let mut context = Self::default();
let source = skip_whitespace(source);
@@ -53,14 +62,17 @@ impl KeyContext {
Self::parse_expr(source, context)
}
+ /// Check if this context is empty.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
+ /// Clear this context.
pub fn clear(&mut self) {
self.0.clear();
}
+ /// Extend this context with another context.
pub fn extend(&mut self, other: &Self) {
for entry in &other.0 {
if !self.contains(&entry.key) {
@@ -69,6 +81,7 @@ impl KeyContext {
}
}
+ /// Add an identifier to this context, if it's not already in this context.
pub fn add<I: Into<SharedString>>(&mut self, identifier: I) {
let key = identifier.into();
@@ -77,6 +90,7 @@ impl KeyContext {
}
}
+ /// Set a key value pair in this context, if it's not already set.
pub fn set<S1: Into<SharedString>, S2: Into<SharedString>>(&mut self, key: S1, value: S2) {
let key = key.into();
if !self.contains(&key) {
@@ -87,10 +101,12 @@ impl KeyContext {
}
}
+ /// Check if this context contains a given identifier or key.
pub fn contains(&self, key: &str) -> bool {
self.0.iter().any(|entry| entry.key.as_ref() == key)
}
+ /// Get the associated value for a given identifier or key.
pub fn get(&self, key: &str) -> Option<&SharedString> {
self.0
.iter()
@@ -117,20 +133,31 @@ impl fmt::Debug for KeyContext {
}
}
+/// A datastructure for resolving whether an action should be dispatched
+/// Representing a small language for describing which contexts correspond
+/// to which actions.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum KeyBindingContextPredicate {
+ /// A predicate that will match a given identifier.
Identifier(SharedString),
+ /// A predicate that will match a given key-value pair.
Equal(SharedString, SharedString),
+ /// A predicate that will match a given key-value pair not being present.
NotEqual(SharedString, SharedString),
+ /// A predicate that will match a given predicate appearing below another predicate.
+ /// in the element tree
Child(
Box<KeyBindingContextPredicate>,
Box<KeyBindingContextPredicate>,
),
+ /// Predicate that will invert another predicate.
Not(Box<KeyBindingContextPredicate>),
+ /// A predicate that will match if both of its children match.
And(
Box<KeyBindingContextPredicate>,
Box<KeyBindingContextPredicate>,
),
+ /// A predicate that will match if either of its children match.
Or(
Box<KeyBindingContextPredicate>,
Box<KeyBindingContextPredicate>,
@@ -138,6 +165,34 @@ pub enum KeyBindingContextPredicate {
}
impl KeyBindingContextPredicate {
+ /// Parse a string in the same format as the keymap's context field.
+ ///
+ /// A basic equivalence check against a set of identifiers can performed by
+ /// simply writing a string:
+ ///
+ /// `StatusBar` -> A predicate that will match a context with the identifier `StatusBar`
+ ///
+ /// You can also specify a key-value pair:
+ ///
+ /// `mode == visible` -> A predicate that will match a context with the key `mode`
+ /// with the value `visible`
+ ///
+ /// And a logical operations combining these two checks:
+ ///
+ /// `StatusBar && mode == visible` -> A predicate that will match a context with the
+ /// identifier `StatusBar` and the key `mode`
+ /// with the value `visible`
+ ///
+ ///
+ /// There is also a special child `>` operator that will match a predicate that is
+ /// below another predicate:
+ ///
+ /// `StatusBar > mode == visible` -> A predicate that will match a context identifier `StatusBar`
+ /// and a child context that has the key `mode` with the
+ /// value `visible`
+ ///
+ /// This syntax supports `!=`, `||` and `&&` as logical operators.
+ /// You can also preface an operation or check with a `!` to negate it.
pub fn parse(source: &str) -> Result<Self> {
let source = skip_whitespace(source);
let (predicate, rest) = Self::parse_expr(source, 0)?;
@@ -148,6 +203,7 @@ impl KeyBindingContextPredicate {
}
}
+ /// Eval a predicate against a set of contexts, arranged from lowest to highest.
pub fn eval(&self, contexts: &[KeyContext]) -> bool {
let Some(context) = contexts.last() else {
return false;
@@ -6,9 +6,12 @@ use std::{
collections::HashMap,
};
+/// An opaque identifier of which version of the keymap is currently active.
+/// The keymap's version is changed whenever bindings are added or removed.
#[derive(Copy, Clone, Eq, PartialEq, Default)]
pub struct KeymapVersion(usize);
+/// A collection of key bindings for the user's application.
#[derive(Default)]
pub struct Keymap {
bindings: Vec<KeyBinding>,
@@ -19,16 +22,19 @@ pub struct Keymap {
}
impl Keymap {
+ /// Create a new keymap with the given bindings.
pub fn new(bindings: Vec<KeyBinding>) -> Self {
let mut this = Self::default();
this.add_bindings(bindings);
this
}
+ /// Get the current version of the keymap.
pub fn version(&self) -> KeymapVersion {
self.version
}
+ /// Add more bindings to the keymap.
pub fn add_bindings<T: IntoIterator<Item = KeyBinding>>(&mut self, bindings: T) {
let no_action_id = (NoAction {}).type_id();
@@ -51,6 +57,7 @@ impl Keymap {
self.version.0 += 1;
}
+ /// Reset this keymap to its initial state.
pub fn clear(&mut self) {
self.bindings.clear();
self.binding_indices_by_action_id.clear();
@@ -77,6 +84,7 @@ impl Keymap {
.filter(move |binding| binding.action().partial_eq(action))
}
+ /// Check if the given binding is enabled, given a certain key context.
pub fn binding_enabled(&self, binding: &KeyBinding, context: &[KeyContext]) -> bool {
// If binding has a context predicate, it must match the current context,
if let Some(predicate) = &binding.context_predicate {
@@ -2,7 +2,7 @@ use crate::{Action, KeyContext, Keymap, KeymapVersion, Keystroke};
use parking_lot::Mutex;
use std::sync::Arc;
-pub struct KeystrokeMatcher {
+pub(crate) struct KeystrokeMatcher {
pending_keystrokes: Vec<Keystroke>,
keymap: Arc<Mutex<Keymap>>,
keymap_version: KeymapVersion,
@@ -35,7 +35,7 @@ impl KeystrokeMatcher {
/// - KeyMatch::Complete(matches) =>
/// One or more bindings have received the necessary key presses.
/// Bindings added later will take precedence over earlier bindings.
- pub fn match_keystroke(
+ pub(crate) fn match_keystroke(
&mut self,
keystroke: &Keystroke,
context_stack: &[KeyContext],
@@ -85,6 +85,10 @@ impl KeystrokeMatcher {
}
}
+/// The result of matching a keystroke against a given keybinding.
+/// - KeyMatch::None => No match is valid for this key given any pending keystrokes.
+/// - KeyMatch::Pending => There exist bindings that is still waiting for more keys.
+/// - KeyMatch::Some(matches) => One or more bindings have received the necessary key presses.
#[derive(Debug)]
pub enum KeyMatch {
None,
@@ -92,19 +96,6 @@ pub enum KeyMatch {
Some(Vec<Box<dyn Action>>),
}
-impl KeyMatch {
- pub fn is_some(&self) -> bool {
- matches!(self, KeyMatch::Some(_))
- }
-
- pub fn matches(self) -> Option<Vec<Box<dyn Action>>> {
- match self {
- KeyMatch::Some(matches) => Some(matches),
- _ => None,
- }
- }
-}
-
impl PartialEq for KeyMatch {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
@@ -6,4 +6,4 @@ mod matcher;
pub use binding::*;
pub use context::*;
pub use keymap::*;
-pub use matcher::*;
+pub(crate) use matcher::*;
@@ -1,3 +1,7 @@
+//! The GPUI prelude is a collection of traits and types that are widely used
+//! throughout the library. It is recommended to import this prelude into your
+//! application to avoid having to import each trait individually.
+
pub use crate::{
util::FluentBuilder, BorrowAppContext, BorrowWindow, Context, Element, FocusableElement,
InteractiveElement, IntoElement, ParentElement, Refineable, Render, RenderOnce,
@@ -10,12 +10,12 @@ pub(crate) type PointF = Point<f32>;
#[allow(non_camel_case_types, unused)]
pub(crate) type PathVertex_ScaledPixels = PathVertex<ScaledPixels>;
-pub type LayerId = u32;
-pub type DrawOrder = u32;
+pub(crate) type LayerId = u32;
+pub(crate) type DrawOrder = u32;
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
-pub struct ViewId {
+pub(crate) struct ViewId {
low_bits: u32,
high_bits: u32,
}
@@ -38,7 +38,7 @@ impl From<ViewId> for EntityId {
}
#[derive(Default)]
-pub struct Scene {
+pub(crate) struct Scene {
layers_by_order: BTreeMap<StackingOrder, LayerId>,
orders_by_layer: BTreeMap<LayerId, StackingOrder>,
pub(crate) shadows: Vec<Shadow>,
@@ -429,7 +429,7 @@ impl<'a> Iterator for BatchIterator<'a> {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Default)]
-pub enum PrimitiveKind {
+pub(crate) enum PrimitiveKind {
Shadow,
#[default]
Quad,
@@ -495,7 +495,7 @@ pub(crate) enum PrimitiveBatch<'a> {
#[derive(Default, Debug, Clone, Eq, PartialEq)]
#[repr(C)]
-pub struct Quad {
+pub(crate) struct Quad {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
@@ -527,7 +527,7 @@ impl From<Quad> for Primitive {
#[derive(Debug, Clone, Eq, PartialEq)]
#[repr(C)]
-pub struct Underline {
+pub(crate) struct Underline {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
@@ -558,7 +558,7 @@ impl From<Underline> for Primitive {
#[derive(Debug, Clone, Eq, PartialEq)]
#[repr(C)]
-pub struct Shadow {
+pub(crate) struct Shadow {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
@@ -655,7 +655,7 @@ impl From<PolychromeSprite> for Primitive {
}
#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Surface {
+pub(crate) struct Surface {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
@@ -685,6 +685,7 @@ impl From<Surface> for Primitive {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) struct PathId(pub(crate) usize);
+/// A line made up of a series of vertices and control points.
#[derive(Debug)]
pub struct Path<P: Clone + Default + Debug> {
pub(crate) id: PathId,
@@ -701,6 +702,7 @@ pub struct Path<P: Clone + Default + Debug> {
}
impl Path<Pixels> {
+ /// Create a new path with the given starting point.
pub fn new(start: Point<Pixels>) -> Self {
Self {
id: PathId(0),
@@ -720,6 +722,7 @@ impl Path<Pixels> {
}
}
+ /// Scale this path by the given factor.
pub fn scale(&self, factor: f32) -> Path<ScaledPixels> {
Path {
id: self.id,
@@ -740,6 +743,7 @@ impl Path<Pixels> {
}
}
+ /// Draw a straight line from the current point to the given point.
pub fn line_to(&mut self, to: Point<Pixels>) {
self.contour_count += 1;
if self.contour_count > 1 {
@@ -751,6 +755,7 @@ impl Path<Pixels> {
self.current = to;
}
+ /// Draw a curve from the current point to the given point, using the given control point.
pub fn curve_to(&mut self, to: Point<Pixels>, ctrl: Point<Pixels>) {
self.contour_count += 1;
if self.contour_count > 1 {
@@ -833,7 +838,7 @@ impl From<Path<ScaledPixels>> for Primitive {
#[derive(Clone, Debug)]
#[repr(C)]
-pub struct PathVertex<P: Clone + Default + Debug> {
+pub(crate) struct PathVertex<P: Clone + Default + Debug> {
pub(crate) xy_position: Point<P>,
pub(crate) st_position: Point<f32>,
pub(crate) content_mask: ContentMask<P>,
@@ -850,4 +855,4 @@ impl PathVertex<Pixels> {
}
#[derive(Copy, Clone, Debug)]
-pub struct AtlasId(pub(crate) usize);
+pub(crate) struct AtlasId(pub(crate) usize);
@@ -3,6 +3,8 @@ use serde::{Deserialize, Serialize};
use std::{borrow::Borrow, sync::Arc};
use util::arc_cow::ArcCow;
+/// A shared string is an immutable string that can be cheaply cloned in GPUI
+/// tasks. Essentially an abstraction over an Arc<str> and &'static str,
#[derive(Deref, DerefMut, Eq, PartialEq, Hash, Clone)]
pub struct SharedString(ArcCow<'static, str>);
@@ -147,12 +147,17 @@ where
}
}
+/// A handle to a subscription created by GPUI. When dropped, the subscription
+/// is cancelled and the callback will no longer be invoked.
#[must_use]
pub struct Subscription {
unsubscribe: Option<Box<dyn FnOnce() + 'static>>,
}
impl Subscription {
+ /// Detaches the subscription from this handle. The callback will
+ /// continue to be invoked until the views or models it has been
+ /// subscribed to are dropped
pub fn detach(mut self) {
self.unsubscribe.take();
}
@@ -3,12 +3,12 @@ use anyhow::anyhow;
use std::{hash::Hash, sync::Arc};
#[derive(Clone, PartialEq, Hash, Eq)]
-pub struct RenderSvgParams {
+pub(crate) struct RenderSvgParams {
pub(crate) path: SharedString,
pub(crate) size: Size<DevicePixels>,
}
-pub struct SvgRenderer {
+pub(crate) struct SvgRenderer {
asset_source: Arc<dyn AssetSource>,
}
@@ -229,6 +229,7 @@ impl TaffyLayoutEngine {
}
}
+/// A unique identifier for a layout node, generated when requesting a layout from Taffy
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(transparent)]
pub struct LayoutId(NodeId);
@@ -440,6 +441,7 @@ where
}
}
+/// The space available for an element to be laid out in
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub enum AvailableSpace {
/// The amount of space available is the specified number of pixels
@@ -34,6 +34,9 @@ use std::{
panic::{self, RefUnwindSafe},
};
+/// Run the given test function with the confifured paremeters.
+/// This is intended for use with the `gpui::test` macro
+/// and generally should not be used directly.
pub fn run_test(
mut num_iterations: u64,
max_retries: usize,
@@ -78,6 +81,7 @@ pub fn run_test(
}
}
+/// A test struct for converting an observation callback into a stream.
pub struct Observation<T> {
rx: channel::Receiver<T>,
_subscription: Subscription,
@@ -377,7 +377,7 @@ impl TextSystem {
Ok(lines)
}
- pub fn finish_frame(&self, reused_views: &FxHashSet<EntityId>) {
+ pub(crate) fn finish_frame(&self, reused_views: &FxHashSet<EntityId>) {
self.line_layout_cache.finish_frame(reused_views)
}
@@ -24,6 +24,7 @@ pub struct ShapedLine {
}
impl ShapedLine {
+ /// The length of the line in utf-8 bytes.
pub fn len(&self) -> usize {
self.layout.len
}