Checkpoint
This commit is contained in:
parent
ce30a689a0
commit
27fb381cca
82 changed files with 661 additions and 1907 deletions
|
@ -1,9 +1,9 @@
|
||||||
use collections::{CommandPaletteFilter, HashMap};
|
use collections::{CommandPaletteFilter, HashMap};
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, Action, AppContext, Component, Div, EventEmitter, FocusHandle, Keystroke,
|
actions, div, prelude::*, Action, AppContext, Component, EventEmitter, FocusHandle, Keystroke,
|
||||||
ParentElement, Render, StatelessInteractive, Styled, View, ViewContext, VisualContext,
|
Node, ParentComponent, Render, Styled, View, ViewContext, VisualContext, WeakView,
|
||||||
WeakView, WindowContext,
|
WindowContext,
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -77,7 +77,7 @@ impl Modal for CommandPalette {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for CommandPalette {
|
impl Render for CommandPalette {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
v_stack().w_96().child(self.picker.clone())
|
v_stack().w_96().child(self.picker.clone())
|
||||||
|
@ -148,7 +148,7 @@ impl CommandPaletteDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for CommandPaletteDelegate {
|
impl PickerDelegate for CommandPaletteDelegate {
|
||||||
type ListItem = Div<Picker<Self>>;
|
type ListItem = Node<Picker<Self>>;
|
||||||
|
|
||||||
fn placeholder_text(&self) -> Arc<str> {
|
fn placeholder_text(&self) -> Arc<str> {
|
||||||
"Execute a command...".into()
|
"Execute a command...".into()
|
||||||
|
|
|
@ -39,12 +39,12 @@ use futures::FutureExt;
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use git::diff_hunk_to_display;
|
use git::diff_hunk_to_display;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
action, actions, div, point, px, relative, rems, size, uniform_list, AnyElement, AppContext,
|
action, actions, div, point, prelude::*, px, relative, rems, size, uniform_list, AnyElement,
|
||||||
AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context,
|
AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context,
|
||||||
EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla,
|
EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla,
|
||||||
InputHandler, KeyContext, Model, MouseButton, ParentElement, Pixels, Render,
|
InputHandler, KeyContext, Model, MouseButton, ParentComponent, Pixels, Render, Styled,
|
||||||
StatelessInteractive, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, View,
|
Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext,
|
||||||
ViewContext, VisualContext, WeakView, WindowContext,
|
WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||||
use hover_popover::{hide_hover, HoverState};
|
use hover_popover::{hide_hover, HoverState};
|
||||||
|
|
|
@ -2442,7 +2442,7 @@ enum Invisible {
|
||||||
impl Element<Editor> for EditorElement {
|
impl Element<Editor> for EditorElement {
|
||||||
type ElementState = ();
|
type ElementState = ();
|
||||||
|
|
||||||
fn id(&self) -> Option<gpui::ElementId> {
|
fn element_id(&self) -> Option<gpui::ElementId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use collections::HashSet;
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, EventEmitter,
|
div, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, EventEmitter,
|
||||||
FocusHandle, Model, ParentElement, Pixels, SharedString, Styled, Subscription, Task, View,
|
FocusHandle, Model, ParentComponent, Pixels, SharedString, Styled, Subscription, Task, View,
|
||||||
ViewContext, VisualContext, WeakView,
|
ViewContext, VisualContext, WeakView,
|
||||||
};
|
};
|
||||||
use language::{
|
use language::{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor};
|
use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString,
|
actions, div, prelude::*, AppContext, EventEmitter, Node, ParentComponent, Render,
|
||||||
StatelessInteractive, Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
|
SharedString, Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
|
||||||
};
|
};
|
||||||
use text::{Bias, Point};
|
use text::{Bias, Point};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
|
@ -145,11 +145,11 @@ impl GoToLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for GoToLine {
|
impl Render for GoToLine {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
modal(cx)
|
modal(cx)
|
||||||
.context("GoToLine")
|
.key_context("GoToLine")
|
||||||
.on_action(Self::cancel)
|
.on_action(Self::cancel)
|
||||||
.on_action(Self::confirm)
|
.on_action(Self::confirm)
|
||||||
.w_96()
|
.w_96()
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::{any::Any, mem};
|
||||||
pub trait Element<V: 'static> {
|
pub trait Element<V: 'static> {
|
||||||
type ElementState: 'static;
|
type ElementState: 'static;
|
||||||
|
|
||||||
fn id(&self) -> Option<ElementId>;
|
fn element_id(&self) -> Option<ElementId>;
|
||||||
|
|
||||||
/// Called to initialize this element for the current frame. If this
|
/// Called to initialize this element for the current frame. If this
|
||||||
/// element had state in a previous frame, it will be passed in for the 3rd argument.
|
/// element had state in a previous frame, it will be passed in for the 3rd argument.
|
||||||
|
@ -38,7 +38,7 @@ pub trait Element<V: 'static> {
|
||||||
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
|
pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
|
||||||
|
|
||||||
pub trait ParentElement<V: 'static> {
|
pub trait ParentComponent<V: 'static> {
|
||||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
|
||||||
|
|
||||||
fn child(mut self, child: impl Component<V>) -> Self
|
fn child(mut self, child: impl Component<V>) -> Self
|
||||||
|
@ -120,7 +120,7 @@ where
|
||||||
E::ElementState: 'static,
|
E::ElementState: 'static,
|
||||||
{
|
{
|
||||||
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
||||||
let frame_state = if let Some(id) = self.element.id() {
|
let frame_state = if let Some(id) = self.element.element_id() {
|
||||||
cx.with_element_state(id, |element_state, cx| {
|
cx.with_element_state(id, |element_state, cx| {
|
||||||
let element_state = self.element.initialize(view_state, element_state, cx);
|
let element_state = self.element.initialize(view_state, element_state, cx);
|
||||||
((), element_state)
|
((), element_state)
|
||||||
|
@ -142,7 +142,7 @@ where
|
||||||
frame_state: initial_frame_state,
|
frame_state: initial_frame_state,
|
||||||
} => {
|
} => {
|
||||||
frame_state = initial_frame_state;
|
frame_state = initial_frame_state;
|
||||||
if let Some(id) = self.element.id() {
|
if let Some(id) = self.element.element_id() {
|
||||||
layout_id = cx.with_element_state(id, |element_state, cx| {
|
layout_id = cx.with_element_state(id, |element_state, cx| {
|
||||||
let mut element_state = element_state.unwrap();
|
let mut element_state = element_state.unwrap();
|
||||||
let layout_id = self.element.layout(state, &mut element_state, cx);
|
let layout_id = self.element.layout(state, &mut element_state, cx);
|
||||||
|
@ -181,7 +181,7 @@ where
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let bounds = cx.layout_bounds(layout_id);
|
let bounds = cx.layout_bounds(layout_id);
|
||||||
if let Some(id) = self.element.id() {
|
if let Some(id) = self.element.element_id() {
|
||||||
cx.with_element_state(id, |element_state, cx| {
|
cx.with_element_state(id, |element_state, cx| {
|
||||||
let mut element_state = element_state.unwrap();
|
let mut element_state = element_state.unwrap();
|
||||||
self.element
|
self.element
|
||||||
|
@ -351,7 +351,7 @@ where
|
||||||
{
|
{
|
||||||
type ElementState = AnyElement<V>;
|
type ElementState = AnyElement<V>;
|
||||||
|
|
||||||
fn id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
mod div;
|
// mod div;
|
||||||
mod img;
|
mod img;
|
||||||
mod node;
|
mod node;
|
||||||
mod svg;
|
mod svg;
|
||||||
mod text;
|
mod text;
|
||||||
mod uniform_list;
|
mod uniform_list;
|
||||||
|
|
||||||
pub use div::*;
|
// pub use div::*;
|
||||||
pub use img::*;
|
pub use img::*;
|
||||||
|
pub use node::*;
|
||||||
pub use svg::*;
|
pub use svg::*;
|
||||||
pub use text::*;
|
pub use text::*;
|
||||||
pub use uniform_list::*;
|
pub use uniform_list::*;
|
||||||
|
|
|
@ -55,16 +55,6 @@ where
|
||||||
I: ElementInteractivity<V>,
|
I: ElementInteractivity<V>,
|
||||||
F: KeyDispatch<V>,
|
F: KeyDispatch<V>,
|
||||||
{
|
{
|
||||||
pub fn group(mut self, group: impl Into<SharedString>) -> Self {
|
|
||||||
self.group = Some(group.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn z_index(mut self, z_index: u32) -> Self {
|
|
||||||
self.base_style.z_index = Some(z_index);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn context<C>(mut self, context: C) -> Self
|
pub fn context<C>(mut self, context: C) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
@ -77,22 +67,6 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn overflow_hidden(mut self) -> Self {
|
|
||||||
self.base_style.overflow.x = Some(Overflow::Hidden);
|
|
||||||
self.base_style.overflow.y = Some(Overflow::Hidden);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn overflow_hidden_x(mut self) -> Self {
|
|
||||||
self.base_style.overflow.x = Some(Overflow::Hidden);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn overflow_hidden_y(mut self) -> Self {
|
|
||||||
self.base_style.overflow.y = Some(Overflow::Hidden);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute_style(
|
pub fn compute_style(
|
||||||
&self,
|
&self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
|
@ -135,22 +109,6 @@ impl<V: 'static> Div<V, StatefulInteractivity<V>, NonFocusableKeyDispatch> {
|
||||||
base_style: self.base_style,
|
base_style: self.base_style,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn overflow_scroll(mut self) -> Self {
|
|
||||||
self.base_style.overflow.x = Some(Overflow::Scroll);
|
|
||||||
self.base_style.overflow.y = Some(Overflow::Scroll);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn overflow_x_scroll(mut self) -> Self {
|
|
||||||
self.base_style.overflow.x = Some(Overflow::Scroll);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn overflow_y_scroll(mut self) -> Self {
|
|
||||||
self.base_style.overflow.y = Some(Overflow::Scroll);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Div<V, StatelessInteractivity<V>, NonFocusableKeyDispatch> {
|
impl<V: 'static> Div<V, StatelessInteractivity<V>, NonFocusableKeyDispatch> {
|
||||||
|
|
|
@ -1,35 +1,28 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
div, AnyElement, BorrowWindow, Bounds, Component, Div, DivState, Element, ElementId,
|
AnyElement, BorrowWindow, Bounds, Component, Element, InteractiveComponent,
|
||||||
ElementInteractivity, FocusListeners, Focusable, FocusableKeyDispatch, KeyDispatch, LayoutId,
|
InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement,
|
||||||
NonFocusableKeyDispatch, Pixels, SharedString, StatefulInteractive, StatefulInteractivity,
|
Styled, ViewContext,
|
||||||
StatelessInteractive, StatelessInteractivity, StyleRefinement, Styled, ViewContext,
|
|
||||||
};
|
};
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
pub struct Img<
|
pub struct Img<V: 'static> {
|
||||||
V: 'static,
|
interactivity: Interactivity<V>,
|
||||||
I: ElementInteractivity<V> = StatelessInteractivity<V>,
|
|
||||||
F: KeyDispatch<V> = NonFocusableKeyDispatch,
|
|
||||||
> {
|
|
||||||
base: Div<V, I, F>,
|
|
||||||
uri: Option<SharedString>,
|
uri: Option<SharedString>,
|
||||||
grayscale: bool,
|
grayscale: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn img<V: 'static>() -> Img<V, StatelessInteractivity<V>, NonFocusableKeyDispatch> {
|
pub fn img<V: 'static>() -> Img<V> {
|
||||||
Img {
|
Img {
|
||||||
base: div(),
|
interactivity: Interactivity::default(),
|
||||||
uri: None,
|
uri: None,
|
||||||
grayscale: false,
|
grayscale: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> Img<V, I, F>
|
impl<V> Img<V>
|
||||||
where
|
where
|
||||||
V: 'static,
|
V: 'static,
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
{
|
||||||
pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
|
pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
|
||||||
self.uri = Some(uri.into());
|
self.uri = Some(uri.into());
|
||||||
|
@ -42,38 +35,17 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, F> Img<V, StatelessInteractivity<V>, F>
|
impl<V> Component<V> for Img<V> {
|
||||||
where
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
pub fn id(self, id: impl Into<ElementId>) -> Img<V, StatefulInteractivity<V>, F> {
|
|
||||||
Img {
|
|
||||||
base: self.base.id(id),
|
|
||||||
uri: self.uri,
|
|
||||||
grayscale: self.grayscale,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, I, F> Component<V> for Img<V, I, F>
|
|
||||||
where
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn render(self) -> AnyElement<V> {
|
fn render(self) -> AnyElement<V> {
|
||||||
AnyElement::new(self)
|
AnyElement::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> Element<V> for Img<V, I, F>
|
impl<V> Element<V> for Img<V> {
|
||||||
where
|
type ElementState = InteractiveElementState;
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
type ElementState = DivState;
|
|
||||||
|
|
||||||
fn id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<crate::ElementId> {
|
||||||
self.base.id()
|
self.interactivity.element_id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize(
|
fn initialize(
|
||||||
|
@ -82,7 +54,7 @@ where
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::ElementState>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> Self::ElementState {
|
) -> Self::ElementState {
|
||||||
self.base.initialize(view_state, element_state, cx)
|
self.interactivity.initialize(element_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
|
@ -91,7 +63,9 @@ where
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::ElementState,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> LayoutId {
|
) -> LayoutId {
|
||||||
self.base.layout(view_state, element_state, cx)
|
self.interactivity.layout(element_state, cx, |style, cx| {
|
||||||
|
cx.request_layout(&style, None)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
|
@ -101,86 +75,50 @@ where
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::ElementState,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
cx.with_z_index(0, |cx| {
|
self.interactivity.paint(
|
||||||
self.base.paint(bounds, view, element_state, cx);
|
bounds,
|
||||||
});
|
bounds.size,
|
||||||
|
element_state,
|
||||||
|
cx,
|
||||||
|
|style, scroll_offset, cx| {
|
||||||
|
let corner_radii = style.corner_radii;
|
||||||
|
|
||||||
let style = self.base.compute_style(bounds, element_state, cx);
|
if let Some(uri) = self.uri.clone() {
|
||||||
let corner_radii = style.corner_radii;
|
// eprintln!(">>> image_cache.get({uri}");
|
||||||
|
let image_future = cx.image_cache.get(uri.clone());
|
||||||
if let Some(uri) = self.uri.clone() {
|
// eprintln!("<<< image_cache.get({uri}");
|
||||||
// eprintln!(">>> image_cache.get({uri}");
|
if let Some(data) = image_future
|
||||||
let image_future = cx.image_cache.get(uri.clone());
|
.clone()
|
||||||
// eprintln!("<<< image_cache.get({uri}");
|
.now_or_never()
|
||||||
if let Some(data) = image_future
|
.and_then(ResultExt::log_err)
|
||||||
.clone()
|
{
|
||||||
.now_or_never()
|
let corner_radii = corner_radii.to_pixels(bounds.size, cx.rem_size());
|
||||||
.and_then(ResultExt::log_err)
|
cx.with_z_index(1, |cx| {
|
||||||
{
|
cx.paint_image(bounds, corner_radii, data, self.grayscale)
|
||||||
let corner_radii = corner_radii.to_pixels(bounds.size, cx.rem_size());
|
.log_err()
|
||||||
cx.with_z_index(1, |cx| {
|
});
|
||||||
cx.paint_image(bounds, corner_radii, data, self.grayscale)
|
} else {
|
||||||
.log_err()
|
cx.spawn(|_, mut cx| async move {
|
||||||
});
|
if image_future.await.log_err().is_some() {
|
||||||
} else {
|
cx.on_next_frame(|cx| cx.notify());
|
||||||
cx.spawn(|_, mut cx| async move {
|
}
|
||||||
if image_future.await.log_err().is_some() {
|
})
|
||||||
cx.on_next_frame(|cx| cx.notify());
|
.detach()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.detach()
|
},
|
||||||
}
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> Styled for Img<V, I, F>
|
impl<V> Styled for Img<V> {
|
||||||
where
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn style(&mut self) -> &mut StyleRefinement {
|
fn style(&mut self) -> &mut StyleRefinement {
|
||||||
self.base.style()
|
&mut self.interactivity.base_style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> StatelessInteractive<V> for Img<V, I, F>
|
impl<V> InteractiveComponent<V> for Img<V> {
|
||||||
where
|
fn interactivity(&mut self) -> &mut Interactivity<V> {
|
||||||
I: ElementInteractivity<V>,
|
&mut self.interactivity
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
|
|
||||||
self.base.stateless_interactivity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, F> StatefulInteractive<V> for Img<V, StatefulInteractivity<V>, F>
|
|
||||||
where
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<V> {
|
|
||||||
self.base.stateful_interactivity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, I> Focusable<V> for Img<V, I, FocusableKeyDispatch<V>>
|
|
||||||
where
|
|
||||||
V: 'static,
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
{
|
|
||||||
fn focus_listeners(&mut self) -> &mut FocusListeners<V> {
|
|
||||||
self.base.focus_listeners()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_focus_style(&mut self, style: StyleRefinement) {
|
|
||||||
self.base.set_focus_style(style)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_focus_in_style(&mut self, style: StyleRefinement) {
|
|
||||||
self.base.set_focus_in_style(style)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_in_focus_style(&mut self, style: StyleRefinement) {
|
|
||||||
self.base.set_in_focus_style(style)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext,
|
point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext,
|
||||||
BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusEvent, FocusHandle,
|
BorrowWindow, Bounds, ClickEvent, Component, DispatchPhase, Element, ElementId, FocusEvent,
|
||||||
KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent,
|
FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent,
|
||||||
MouseUpEvent, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, Style,
|
MouseMoveEvent, MouseUpEvent, ParentComponent, Pixels, Point, Render, ScrollWheelEvent,
|
||||||
StyleRefinement, Styled, Task, View, ViewContext, Visibility,
|
SharedString, Size, Style, StyleRefinement, Styled, Task, View, ViewContext, Visibility,
|
||||||
};
|
};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -32,6 +32,11 @@ pub struct GroupStyle {
|
||||||
pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
|
pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
|
||||||
fn interactivity(&mut self) -> &mut Interactivity<V>;
|
fn interactivity(&mut self) -> &mut Interactivity<V>;
|
||||||
|
|
||||||
|
fn group(mut self, group: impl Into<SharedString>) -> Self {
|
||||||
|
self.interactivity().group = Some(group.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn id(mut self, id: impl Into<ElementId>) -> Stateful<V, Self> {
|
fn id(mut self, id: impl Into<ElementId>) -> Stateful<V, Self> {
|
||||||
self.interactivity().element_id = Some(id.into());
|
self.interactivity().element_id = Some(id.into());
|
||||||
|
|
||||||
|
@ -41,9 +46,9 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn track_focus(mut self, focus_handle: FocusHandle) -> Focusable<V, Self> {
|
fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable<V, Self> {
|
||||||
self.interactivity().focusable = true;
|
self.interactivity().focusable = true;
|
||||||
self.interactivity().tracked_focus_handle = Some(focus_handle);
|
self.interactivity().tracked_focus_handle = Some(focus_handle.clone());
|
||||||
Focusable {
|
Focusable {
|
||||||
element: self,
|
element: self,
|
||||||
view_type: PhantomData,
|
view_type: PhantomData,
|
||||||
|
@ -269,8 +274,27 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait StatefulInteractiveComponent<V: 'static, E: Element<V>>: InteractiveComponent<V> {
|
pub trait StatefulInteractiveComponent<V: 'static, E: Element<V>>: InteractiveComponent<V> {
|
||||||
fn focusable(mut self) -> Self {
|
fn focusable(mut self) -> Focusable<V, Self> {
|
||||||
self.interactivity().focusable = true;
|
self.interactivity().focusable = true;
|
||||||
|
Focusable {
|
||||||
|
element: self,
|
||||||
|
view_type: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflow_scroll(mut self) -> Self {
|
||||||
|
self.interactivity().base_style.overflow.x = Some(Overflow::Scroll);
|
||||||
|
self.interactivity().base_style.overflow.y = Some(Overflow::Scroll);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflow_x_scroll(mut self) -> Self {
|
||||||
|
self.interactivity().base_style.overflow.x = Some(Overflow::Scroll);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflow_y_scroll(mut self) -> Self {
|
||||||
|
self.interactivity().base_style.overflow.y = Some(Overflow::Scroll);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,16 +538,16 @@ pub type KeyUpListener<V> =
|
||||||
pub type ActionListener<V> =
|
pub type ActionListener<V> =
|
||||||
Box<dyn Fn(&mut V, &dyn Any, DispatchPhase, &mut ViewContext<V>) + 'static>;
|
Box<dyn Fn(&mut V, &dyn Any, DispatchPhase, &mut ViewContext<V>) + 'static>;
|
||||||
|
|
||||||
pub fn node<V: 'static>() -> Node<V> {
|
pub fn div<V: 'static>() -> Node<V> {
|
||||||
Node {
|
Node {
|
||||||
interactivity: Interactivity::default(),
|
interactivity: Interactivity::default(),
|
||||||
children: Vec::default(),
|
children: SmallVec::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Node<V> {
|
pub struct Node<V> {
|
||||||
interactivity: Interactivity<V>,
|
interactivity: Interactivity<V>,
|
||||||
children: Vec<AnyElement<V>>,
|
children: SmallVec<[AnyElement<V>; 2]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> Styled for Node<V> {
|
impl<V> Styled for Node<V> {
|
||||||
|
@ -538,10 +562,16 @@ impl<V: 'static> InteractiveComponent<V> for Node<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: 'static> ParentComponent<V> for Node<V> {
|
||||||
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
|
&mut self.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for Node<V> {
|
impl<V: 'static> Element<V> for Node<V> {
|
||||||
type ElementState = NodeState;
|
type ElementState = NodeState;
|
||||||
|
|
||||||
fn id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.interactivity.element_id.clone()
|
self.interactivity.element_id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,48 +671,54 @@ impl<V: 'static> Element<V> for Node<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: 'static> Component<V> for Node<V> {
|
||||||
|
fn render(self) -> AnyElement<V> {
|
||||||
|
AnyElement::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct NodeState {
|
pub struct NodeState {
|
||||||
child_layout_ids: SmallVec<[LayoutId; 4]>,
|
child_layout_ids: SmallVec<[LayoutId; 4]>,
|
||||||
interactive_state: InteractiveElementState,
|
interactive_state: InteractiveElementState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Interactivity<V> {
|
pub struct Interactivity<V> {
|
||||||
element_id: Option<ElementId>,
|
pub element_id: Option<ElementId>,
|
||||||
key_context: KeyContext,
|
pub key_context: KeyContext,
|
||||||
focusable: bool,
|
pub focusable: bool,
|
||||||
tracked_focus_handle: Option<FocusHandle>,
|
pub tracked_focus_handle: Option<FocusHandle>,
|
||||||
focus_listeners: FocusListeners<V>,
|
pub focus_listeners: FocusListeners<V>,
|
||||||
scroll_offset: Point<Pixels>,
|
// pub scroll_offset: Point<Pixels>,
|
||||||
group: Option<SharedString>,
|
pub group: Option<SharedString>,
|
||||||
base_style: StyleRefinement,
|
pub base_style: StyleRefinement,
|
||||||
focus_style: StyleRefinement,
|
pub focus_style: StyleRefinement,
|
||||||
focus_in_style: StyleRefinement,
|
pub focus_in_style: StyleRefinement,
|
||||||
in_focus_style: StyleRefinement,
|
pub in_focus_style: StyleRefinement,
|
||||||
hover_style: StyleRefinement,
|
pub hover_style: StyleRefinement,
|
||||||
group_hover_style: Option<GroupStyle>,
|
pub group_hover_style: Option<GroupStyle>,
|
||||||
active_style: StyleRefinement,
|
pub active_style: StyleRefinement,
|
||||||
group_active_style: Option<GroupStyle>,
|
pub group_active_style: Option<GroupStyle>,
|
||||||
drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
||||||
group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
||||||
mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
|
pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
|
||||||
mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
|
pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
|
||||||
mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
|
pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
|
||||||
scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
|
pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
|
||||||
key_down_listeners: SmallVec<[KeyDownListener<V>; 2]>,
|
pub key_down_listeners: SmallVec<[KeyDownListener<V>; 2]>,
|
||||||
key_up_listeners: SmallVec<[KeyUpListener<V>; 2]>,
|
pub key_up_listeners: SmallVec<[KeyUpListener<V>; 2]>,
|
||||||
action_listeners: SmallVec<[(TypeId, ActionListener<V>); 8]>,
|
pub action_listeners: SmallVec<[(TypeId, ActionListener<V>); 8]>,
|
||||||
drop_listeners: SmallVec<[(TypeId, Box<DropListener<V>>); 2]>,
|
pub drop_listeners: SmallVec<[(TypeId, Box<DropListener<V>>); 2]>,
|
||||||
click_listeners: SmallVec<[ClickListener<V>; 2]>,
|
pub click_listeners: SmallVec<[ClickListener<V>; 2]>,
|
||||||
drag_listener: Option<DragListener<V>>,
|
pub drag_listener: Option<DragListener<V>>,
|
||||||
hover_listener: Option<HoverListener<V>>,
|
pub hover_listener: Option<HoverListener<V>>,
|
||||||
tooltip_builder: Option<TooltipBuilder<V>>,
|
pub tooltip_builder: Option<TooltipBuilder<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> Interactivity<V>
|
impl<V> Interactivity<V>
|
||||||
where
|
where
|
||||||
V: 'static,
|
V: 'static,
|
||||||
{
|
{
|
||||||
fn initialize(
|
pub fn initialize(
|
||||||
&mut self,
|
&mut self,
|
||||||
element_state: Option<InteractiveElementState>,
|
element_state: Option<InteractiveElementState>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
|
@ -703,7 +739,7 @@ where
|
||||||
element_state
|
element_state
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
pub fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
element_state: &mut InteractiveElementState,
|
element_state: &mut InteractiveElementState,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
|
@ -719,7 +755,7 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
pub fn paint(
|
||||||
&mut self,
|
&mut self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
content_size: Size<Pixels>,
|
content_size: Size<Pixels>,
|
||||||
|
@ -996,6 +1032,11 @@ where
|
||||||
GroupBounds::push(group, bounds, cx);
|
GroupBounds::push(group, bounds, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scroll_offset = element_state
|
||||||
|
.scroll_offset
|
||||||
|
.as_ref()
|
||||||
|
.map(|scroll_offset| *scroll_offset.lock());
|
||||||
|
|
||||||
cx.with_element_id(self.element_id.clone(), |cx| {
|
cx.with_element_id(self.element_id.clone(), |cx| {
|
||||||
cx.with_key_dispatch(
|
cx.with_key_dispatch(
|
||||||
self.key_context.clone(),
|
self.key_context.clone(),
|
||||||
|
@ -1026,7 +1067,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f(style, self.scroll_offset, cx)
|
f(style, scroll_offset.unwrap_or_default(), cx)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1036,7 +1077,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_style(
|
pub fn compute_style(
|
||||||
&self,
|
&self,
|
||||||
bounds: Option<Bounds<Pixels>>,
|
bounds: Option<Bounds<Pixels>>,
|
||||||
element_state: &mut InteractiveElementState,
|
element_state: &mut InteractiveElementState,
|
||||||
|
@ -1118,7 +1159,7 @@ impl<V: 'static> Default for Interactivity<V> {
|
||||||
focusable: false,
|
focusable: false,
|
||||||
tracked_focus_handle: None,
|
tracked_focus_handle: None,
|
||||||
focus_listeners: SmallVec::default(),
|
focus_listeners: SmallVec::default(),
|
||||||
scroll_offset: Point::default(),
|
// scroll_offset: Point::default(),
|
||||||
group: None,
|
group: None,
|
||||||
base_style: StyleRefinement::default(),
|
base_style: StyleRefinement::default(),
|
||||||
focus_style: StyleRefinement::default(),
|
focus_style: StyleRefinement::default(),
|
||||||
|
@ -1148,15 +1189,15 @@ impl<V: 'static> Default for Interactivity<V> {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct InteractiveElementState {
|
pub struct InteractiveElementState {
|
||||||
focus_handle: Option<FocusHandle>,
|
pub focus_handle: Option<FocusHandle>,
|
||||||
clicked_state: Arc<Mutex<ElementClickedState>>,
|
pub clicked_state: Arc<Mutex<ElementClickedState>>,
|
||||||
hover_state: Arc<Mutex<bool>>,
|
pub hover_state: Arc<Mutex<bool>>,
|
||||||
pending_mouse_down: Arc<Mutex<Option<MouseDownEvent>>>,
|
pub pending_mouse_down: Arc<Mutex<Option<MouseDownEvent>>>,
|
||||||
scroll_offset: Option<Arc<Mutex<Point<Pixels>>>>,
|
pub scroll_offset: Option<Arc<Mutex<Point<Pixels>>>>,
|
||||||
active_tooltip: Arc<Mutex<Option<ActiveTooltip>>>,
|
pub active_tooltip: Arc<Mutex<Option<ActiveTooltip>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ActiveTooltip {
|
pub struct ActiveTooltip {
|
||||||
#[allow(unused)] // used to drop the task
|
#[allow(unused)] // used to drop the task
|
||||||
waiting: Option<Task<()>>,
|
waiting: Option<Task<()>>,
|
||||||
tooltip: Option<AnyTooltip>,
|
tooltip: Option<AnyTooltip>,
|
||||||
|
@ -1164,7 +1205,7 @@ struct ActiveTooltip {
|
||||||
|
|
||||||
/// Whether or not the element or a group that contains it is clicked by the mouse.
|
/// Whether or not the element or a group that contains it is clicked by the mouse.
|
||||||
#[derive(Copy, Clone, Default, Eq, PartialEq)]
|
#[derive(Copy, Clone, Default, Eq, PartialEq)]
|
||||||
struct ElementClickedState {
|
pub struct ElementClickedState {
|
||||||
pub group: bool,
|
pub group: bool,
|
||||||
pub element: bool,
|
pub element: bool,
|
||||||
}
|
}
|
||||||
|
@ -1222,6 +1263,16 @@ impl<V: 'static, E: StatefulInteractiveComponent<V, E>> StatefulInteractiveCompo
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V, E> Styled for Focusable<V, E>
|
||||||
|
where
|
||||||
|
V: 'static,
|
||||||
|
E: Styled,
|
||||||
|
{
|
||||||
|
fn style(&mut self) -> &mut StyleRefinement {
|
||||||
|
self.element.style()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V, E> Element<V> for Focusable<V, E>
|
impl<V, E> Element<V> for Focusable<V, E>
|
||||||
where
|
where
|
||||||
V: 'static,
|
V: 'static,
|
||||||
|
@ -1229,8 +1280,8 @@ where
|
||||||
{
|
{
|
||||||
type ElementState = E::ElementState;
|
type ElementState = E::ElementState;
|
||||||
|
|
||||||
fn id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.element.id()
|
self.element.element_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize(
|
fn initialize(
|
||||||
|
@ -1262,11 +1313,41 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V, E> Component<V> for Focusable<V, E>
|
||||||
|
where
|
||||||
|
V: 'static,
|
||||||
|
E: 'static + Element<V>,
|
||||||
|
{
|
||||||
|
fn render(self) -> AnyElement<V> {
|
||||||
|
AnyElement::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, E> ParentComponent<V> for Focusable<V, E>
|
||||||
|
where
|
||||||
|
V: 'static,
|
||||||
|
E: ParentComponent<V>,
|
||||||
|
{
|
||||||
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
|
self.element.children_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Stateful<V, E> {
|
pub struct Stateful<V, E> {
|
||||||
element: E,
|
element: E,
|
||||||
view_type: PhantomData<V>,
|
view_type: PhantomData<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V, E> Styled for Stateful<V, E>
|
||||||
|
where
|
||||||
|
V: 'static,
|
||||||
|
E: Styled,
|
||||||
|
{
|
||||||
|
fn style(&mut self) -> &mut StyleRefinement {
|
||||||
|
self.element.style()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V, E> StatefulInteractiveComponent<V, E> for Stateful<V, E>
|
impl<V, E> StatefulInteractiveComponent<V, E> for Stateful<V, E>
|
||||||
where
|
where
|
||||||
V: 'static,
|
V: 'static,
|
||||||
|
@ -1294,8 +1375,8 @@ where
|
||||||
{
|
{
|
||||||
type ElementState = E::ElementState;
|
type ElementState = E::ElementState;
|
||||||
|
|
||||||
fn id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.element.id()
|
self.element.element_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize(
|
fn initialize(
|
||||||
|
@ -1326,3 +1407,23 @@ where
|
||||||
self.element.paint(bounds, view_state, element_state, cx)
|
self.element.paint(bounds, view_state, element_state, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V, E> Component<V> for Stateful<V, E>
|
||||||
|
where
|
||||||
|
V: 'static,
|
||||||
|
E: 'static + Element<V>,
|
||||||
|
{
|
||||||
|
fn render(self) -> AnyElement<V> {
|
||||||
|
AnyElement::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, E> ParentComponent<V> for Stateful<V, E>
|
||||||
|
where
|
||||||
|
V: 'static,
|
||||||
|
E: ParentComponent<V>,
|
||||||
|
{
|
||||||
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
|
self.element.children_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,69 +1,40 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
div, AnyElement, Bounds, Component, Div, DivState, Element, ElementId, ElementInteractivity,
|
AnyElement, Bounds, Component, Element, ElementId, InteractiveComponent,
|
||||||
FocusListeners, Focusable, FocusableKeyDispatch, KeyDispatch, LayoutId,
|
InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement,
|
||||||
NonFocusableKeyDispatch, Pixels, SharedString, StatefulInteractive, StatefulInteractivity,
|
Styled, ViewContext,
|
||||||
StatelessInteractive, StatelessInteractivity, StyleRefinement, Styled, ViewContext,
|
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
pub struct Svg<
|
pub struct Svg<V: 'static> {
|
||||||
V: 'static,
|
interactivity: Interactivity<V>,
|
||||||
I: ElementInteractivity<V> = StatelessInteractivity<V>,
|
|
||||||
F: KeyDispatch<V> = NonFocusableKeyDispatch,
|
|
||||||
> {
|
|
||||||
base: Div<V, I, F>,
|
|
||||||
path: Option<SharedString>,
|
path: Option<SharedString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn svg<V: 'static>() -> Svg<V, StatelessInteractivity<V>, NonFocusableKeyDispatch> {
|
pub fn svg<V: 'static>() -> Svg<V> {
|
||||||
Svg {
|
Svg {
|
||||||
base: div(),
|
interactivity: Interactivity::default(),
|
||||||
path: None,
|
path: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> Svg<V, I, F>
|
impl<V> Svg<V> {
|
||||||
where
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
pub fn path(mut self, path: impl Into<SharedString>) -> Self {
|
pub fn path(mut self, path: impl Into<SharedString>) -> Self {
|
||||||
self.path = Some(path.into());
|
self.path = Some(path.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, F> Svg<V, StatelessInteractivity<V>, F>
|
impl<V> Component<V> for Svg<V> {
|
||||||
where
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
pub fn id(self, id: impl Into<ElementId>) -> Svg<V, StatefulInteractivity<V>, F> {
|
|
||||||
Svg {
|
|
||||||
base: self.base.id(id),
|
|
||||||
path: self.path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, I, F> Component<V> for Svg<V, I, F>
|
|
||||||
where
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn render(self) -> AnyElement<V> {
|
fn render(self) -> AnyElement<V> {
|
||||||
AnyElement::new(self)
|
AnyElement::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> Element<V> for Svg<V, I, F>
|
impl<V> Element<V> for Svg<V> {
|
||||||
where
|
type ElementState = InteractiveElementState;
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
type ElementState = DivState;
|
|
||||||
|
|
||||||
fn id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.base.id()
|
self.interactivity.element_id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize(
|
fn initialize(
|
||||||
|
@ -72,7 +43,7 @@ where
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::ElementState>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> Self::ElementState {
|
) -> Self::ElementState {
|
||||||
self.base.initialize(view_state, element_state, cx)
|
self.interactivity.initialize(element_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
|
@ -81,7 +52,9 @@ where
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::ElementState,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> LayoutId {
|
) -> LayoutId {
|
||||||
self.base.layout(view_state, element_state, cx)
|
self.interactivity.layout(element_state, cx, |style, cx| {
|
||||||
|
cx.request_layout(&style, None)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
|
@ -93,65 +66,23 @@ where
|
||||||
) where
|
) where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.base.paint(bounds, view, element_state, cx);
|
self.interactivity
|
||||||
let color = self
|
.paint(bounds, bounds.size, element_state, cx, |style, _, cx| {
|
||||||
.base
|
if let Some((path, color)) = self.path.as_ref().zip(style.text.color) {
|
||||||
.compute_style(bounds, element_state, cx)
|
cx.paint_svg(bounds, path.clone(), color).log_err();
|
||||||
.text
|
}
|
||||||
.color;
|
})
|
||||||
if let Some((path, color)) = self.path.as_ref().zip(color) {
|
|
||||||
cx.paint_svg(bounds, path.clone(), color).log_err();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> Styled for Svg<V, I, F>
|
impl<V> Styled for Svg<V> {
|
||||||
where
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn style(&mut self) -> &mut StyleRefinement {
|
fn style(&mut self) -> &mut StyleRefinement {
|
||||||
self.base.style()
|
&mut self.interactivity.base_style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> StatelessInteractive<V> for Svg<V, I, F>
|
impl<V> InteractiveComponent<V> for Svg<V> {
|
||||||
where
|
fn interactivity(&mut self) -> &mut Interactivity<V> {
|
||||||
I: ElementInteractivity<V>,
|
&mut self.interactivity
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
|
|
||||||
self.base.stateless_interactivity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, F> StatefulInteractive<V> for Svg<V, StatefulInteractivity<V>, F>
|
|
||||||
where
|
|
||||||
V: 'static,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<V> {
|
|
||||||
self.base.stateful_interactivity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: 'static, I> Focusable<V> for Svg<V, I, FocusableKeyDispatch<V>>
|
|
||||||
where
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
{
|
|
||||||
fn focus_listeners(&mut self) -> &mut FocusListeners<V> {
|
|
||||||
self.base.focus_listeners()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_focus_style(&mut self, style: StyleRefinement) {
|
|
||||||
self.base.set_focus_style(style)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_focus_in_style(&mut self, style: StyleRefinement) {
|
|
||||||
self.base.set_focus_in_style(style)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_in_focus_style(&mut self, style: StyleRefinement) {
|
|
||||||
self.base.set_in_focus_style(style)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl<V: 'static> Component<V> for Text<V> {
|
||||||
impl<V: 'static> Element<V> for Text<V> {
|
impl<V: 'static> Element<V> for Text<V> {
|
||||||
type ElementState = Arc<Mutex<Option<TextElementState>>>;
|
type ElementState = Arc<Mutex<Option<TextElementState>>>;
|
||||||
|
|
||||||
fn id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<crate::ElementId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element,
|
point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element,
|
||||||
ElementId, ElementInteractivity, InteractiveElementState, LayoutId, Pixels, Point, Size,
|
ElementId, InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels,
|
||||||
StatefulInteractive, StatefulInteractivity, StatelessInteractive, StatelessInteractivity,
|
Point, Size, StyleRefinement, Styled, ViewContext,
|
||||||
StyleRefinement, Styled, ViewContext,
|
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{cmp, ops::Range, sync::Arc};
|
use std::{cmp, mem, ops::Range, sync::Arc};
|
||||||
use taffy::style::Overflow;
|
use taffy::style::Overflow;
|
||||||
|
|
||||||
/// uniform_list provides lazy rendering for a set of items that are of uniform height.
|
/// uniform_list provides lazy rendering for a set of items that are of uniform height.
|
||||||
/// When rendered into a container with overflow-y: hidden and a fixed (or max) height,
|
/// When rendered into a container with overflow-y: hidden and a fixed (or max) height,
|
||||||
/// uniform_list will only render the visibile subset of items.
|
/// uniform_list will only render the visibile subset of items.
|
||||||
pub fn uniform_list<Id, V, C>(
|
pub fn uniform_list<I, V, C>(
|
||||||
id: Id,
|
id: I,
|
||||||
item_count: usize,
|
item_count: usize,
|
||||||
f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> SmallVec<[C; 64]>,
|
f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> SmallVec<[C; 64]>,
|
||||||
) -> UniformList<V>
|
) -> UniformList<V>
|
||||||
where
|
where
|
||||||
Id: Into<ElementId>,
|
I: Into<ElementId>,
|
||||||
V: 'static,
|
V: 'static,
|
||||||
C: Component<V>,
|
C: Component<V>,
|
||||||
{
|
{
|
||||||
|
@ -37,7 +36,10 @@ where
|
||||||
.map(|component| component.render())
|
.map(|component| component.render())
|
||||||
.collect()
|
.collect()
|
||||||
}),
|
}),
|
||||||
interactivity: StatefulInteractivity::new(id, StatelessInteractivity::default()),
|
interactivity: Interactivity {
|
||||||
|
element_id: Some(id.into()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
scroll_handle: None,
|
scroll_handle: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,7 @@ pub struct UniformList<V: 'static> {
|
||||||
&'a mut ViewContext<V>,
|
&'a mut ViewContext<V>,
|
||||||
) -> SmallVec<[AnyElement<V>; 64]>,
|
) -> SmallVec<[AnyElement<V>; 64]>,
|
||||||
>,
|
>,
|
||||||
interactivity: StatefulInteractivity<V>,
|
interactivity: Interactivity<V>,
|
||||||
scroll_handle: Option<UniformListScrollHandle>,
|
scroll_handle: Option<UniformListScrollHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +105,7 @@ pub struct UniformListState {
|
||||||
impl<V: 'static> Element<V> for UniformList<V> {
|
impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
type ElementState = UniformListState;
|
type ElementState = UniformListState;
|
||||||
|
|
||||||
fn id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<crate::ElementId> {
|
||||||
Some(self.id.clone())
|
Some(self.id.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,13 +115,18 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::ElementState>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> Self::ElementState {
|
) -> Self::ElementState {
|
||||||
element_state.unwrap_or_else(|| {
|
if let Some(mut element_state) = element_state {
|
||||||
|
element_state.interactive = self
|
||||||
|
.interactivity
|
||||||
|
.initialize(Some(element_state.interactive), cx);
|
||||||
|
element_state
|
||||||
|
} else {
|
||||||
let item_size = self.measure_item(view_state, None, cx);
|
let item_size = self.measure_item(view_state, None, cx);
|
||||||
UniformListState {
|
UniformListState {
|
||||||
interactive: InteractiveElementState::default(),
|
interactive: self.interactivity.initialize(None, cx),
|
||||||
item_size,
|
item_size,
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
|
@ -132,35 +139,44 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
let item_size = element_state.item_size;
|
let item_size = element_state.item_size;
|
||||||
let rem_size = cx.rem_size();
|
let rem_size = cx.rem_size();
|
||||||
|
|
||||||
cx.request_measured_layout(
|
self.interactivity
|
||||||
self.computed_style(),
|
.layout(&mut element_state.interactive, cx, |style, cx| {
|
||||||
rem_size,
|
cx.request_measured_layout(
|
||||||
move |known_dimensions: Size<Option<Pixels>>, available_space: Size<AvailableSpace>| {
|
style,
|
||||||
let desired_height = item_size.height * max_items;
|
rem_size,
|
||||||
let width = known_dimensions
|
move |known_dimensions: Size<Option<Pixels>>,
|
||||||
.width
|
available_space: Size<AvailableSpace>| {
|
||||||
.unwrap_or(match available_space.width {
|
let desired_height = item_size.height * max_items;
|
||||||
AvailableSpace::Definite(x) => x,
|
let width = known_dimensions
|
||||||
AvailableSpace::MinContent | AvailableSpace::MaxContent => item_size.width,
|
.width
|
||||||
});
|
.unwrap_or(match available_space.width {
|
||||||
let height = match available_space.height {
|
AvailableSpace::Definite(x) => x,
|
||||||
AvailableSpace::Definite(x) => desired_height.min(x),
|
AvailableSpace::MinContent | AvailableSpace::MaxContent => {
|
||||||
AvailableSpace::MinContent | AvailableSpace::MaxContent => desired_height,
|
item_size.width
|
||||||
};
|
}
|
||||||
size(width, height)
|
});
|
||||||
},
|
let height = match available_space.height {
|
||||||
)
|
AvailableSpace::Definite(x) => desired_height.min(x),
|
||||||
|
AvailableSpace::MinContent | AvailableSpace::MaxContent => {
|
||||||
|
desired_height
|
||||||
|
}
|
||||||
|
};
|
||||||
|
size(width, height)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
&mut self,
|
||||||
bounds: crate::Bounds<crate::Pixels>,
|
bounds: Bounds<crate::Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::ElementState,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
let style = self.computed_style();
|
let style =
|
||||||
|
self.interactivity
|
||||||
|
.compute_style(Some(bounds), &mut element_state.interactive, cx);
|
||||||
let border = style.border_widths.to_pixels(cx.rem_size());
|
let border = style.border_widths.to_pixels(cx.rem_size());
|
||||||
let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size());
|
let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size());
|
||||||
|
|
||||||
|
@ -170,74 +186,75 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
- point(border.right + padding.right, border.bottom + padding.bottom),
|
- point(border.right + padding.right, border.bottom + padding.bottom),
|
||||||
);
|
);
|
||||||
|
|
||||||
cx.with_z_index(style.z_index.unwrap_or(0), |cx| {
|
let item_size = element_state.item_size;
|
||||||
style.paint(bounds, cx);
|
let content_size = Size {
|
||||||
|
width: padded_bounds.size.width,
|
||||||
|
height: item_size.height * self.item_count,
|
||||||
|
};
|
||||||
|
|
||||||
let content_size;
|
let mut interactivity = mem::take(&mut self.interactivity);
|
||||||
if self.item_count > 0 {
|
let shared_scroll_offset = element_state.interactive.scroll_offset.clone().unwrap();
|
||||||
let item_height = self
|
|
||||||
.measure_item(view_state, Some(padded_bounds.size.width), cx)
|
|
||||||
.height;
|
|
||||||
if let Some(scroll_handle) = self.scroll_handle.clone() {
|
|
||||||
scroll_handle.0.lock().replace(ScrollHandleState {
|
|
||||||
item_height,
|
|
||||||
list_height: padded_bounds.size.height,
|
|
||||||
scroll_offset: element_state.interactive.track_scroll_offset(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let visible_item_count = if item_height > px(0.) {
|
|
||||||
(padded_bounds.size.height / item_height).ceil() as usize + 1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
let scroll_offset = element_state
|
|
||||||
.interactive
|
|
||||||
.scroll_offset()
|
|
||||||
.map_or((0.0).into(), |offset| offset.y);
|
|
||||||
let first_visible_element_ix = (-scroll_offset / item_height).floor() as usize;
|
|
||||||
let visible_range = first_visible_element_ix
|
|
||||||
..cmp::min(
|
|
||||||
first_visible_element_ix + visible_item_count,
|
|
||||||
self.item_count,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut items = (self.render_items)(view_state, visible_range.clone(), cx);
|
interactivity.paint(
|
||||||
|
bounds,
|
||||||
|
content_size,
|
||||||
|
&mut element_state.interactive,
|
||||||
|
cx,
|
||||||
|
|style, scroll_offset, cx| {
|
||||||
|
let border = style.border_widths.to_pixels(cx.rem_size());
|
||||||
|
let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size());
|
||||||
|
|
||||||
content_size = Size {
|
let padded_bounds = Bounds::from_corners(
|
||||||
width: padded_bounds.size.width,
|
bounds.origin + point(border.left + padding.left, border.top + padding.top),
|
||||||
height: item_height * self.item_count,
|
bounds.lower_right()
|
||||||
};
|
- point(border.right + padding.right, border.bottom + padding.bottom),
|
||||||
|
|
||||||
cx.with_z_index(1, |cx| {
|
|
||||||
for (item, ix) in items.iter_mut().zip(visible_range) {
|
|
||||||
let item_origin =
|
|
||||||
padded_bounds.origin + point(px(0.), item_height * ix + scroll_offset);
|
|
||||||
let available_space = size(
|
|
||||||
AvailableSpace::Definite(padded_bounds.size.width),
|
|
||||||
AvailableSpace::Definite(item_height),
|
|
||||||
);
|
|
||||||
item.draw(item_origin, available_space, view_state, cx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
content_size = Size {
|
|
||||||
width: bounds.size.width,
|
|
||||||
height: px(0.),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let overflow = point(style.overflow.x, Overflow::Scroll);
|
|
||||||
|
|
||||||
cx.with_z_index(0, |cx| {
|
|
||||||
self.interactivity.handle_events(
|
|
||||||
bounds,
|
|
||||||
content_size,
|
|
||||||
overflow,
|
|
||||||
&mut element_state.interactive,
|
|
||||||
cx,
|
|
||||||
);
|
);
|
||||||
});
|
|
||||||
})
|
cx.with_z_index(style.z_index.unwrap_or(0), |cx| {
|
||||||
|
style.paint(bounds, cx);
|
||||||
|
|
||||||
|
if self.item_count > 0 {
|
||||||
|
let item_height = self
|
||||||
|
.measure_item(view_state, Some(padded_bounds.size.width), cx)
|
||||||
|
.height;
|
||||||
|
if let Some(scroll_handle) = self.scroll_handle.clone() {
|
||||||
|
scroll_handle.0.lock().replace(ScrollHandleState {
|
||||||
|
item_height,
|
||||||
|
list_height: padded_bounds.size.height,
|
||||||
|
scroll_offset: shared_scroll_offset,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let visible_item_count = if item_height > px(0.) {
|
||||||
|
(padded_bounds.size.height / item_height).ceil() as usize + 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
let first_visible_element_ix =
|
||||||
|
(-scroll_offset.y / item_height).floor() as usize;
|
||||||
|
let visible_range = first_visible_element_ix
|
||||||
|
..cmp::min(
|
||||||
|
first_visible_element_ix + visible_item_count,
|
||||||
|
self.item_count,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut items = (self.render_items)(view_state, visible_range.clone(), cx);
|
||||||
|
cx.with_z_index(1, |cx| {
|
||||||
|
for (item, ix) in items.iter_mut().zip(visible_range) {
|
||||||
|
let item_origin = padded_bounds.origin
|
||||||
|
+ point(px(0.), item_height * ix + scroll_offset.y);
|
||||||
|
let available_space = size(
|
||||||
|
AvailableSpace::Definite(padded_bounds.size.width),
|
||||||
|
AvailableSpace::Definite(item_height),
|
||||||
|
);
|
||||||
|
item.draw(item_origin, available_space, view_state, cx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
);
|
||||||
|
self.interactivity = interactivity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,14 +292,8 @@ impl<V> UniformList<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> StatelessInteractive<V> for UniformList<V> {
|
impl<V> InteractiveComponent<V> for UniformList<V> {
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
|
fn interactivity(&mut self) -> &mut crate::Interactivity<V> {
|
||||||
self.interactivity.as_stateless_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: 'static> StatefulInteractive<V> for UniformList<V> {
|
|
||||||
fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<V> {
|
|
||||||
&mut self.interactivity
|
&mut self.interactivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,915 +1,17 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
div, point, px, Action, AnyDrag, AnyTooltip, AnyView, AppContext, Bounds, Component,
|
div, point, px, AnyDrag, AnyTooltip, AnyView, AppContext, Bounds, Component, DispatchPhase,
|
||||||
DispatchPhase, Div, Element, ElementId, FocusHandle, KeyContext, Keystroke, Modifiers,
|
FocusHandle, Keystroke, Modifiers, Node, Pixels, Point, Render, SharedString, StyleRefinement,
|
||||||
Overflow, Pixels, Point, Render, SharedString, Size, Style, StyleRefinement, Task, View,
|
Task, ViewContext,
|
||||||
ViewContext,
|
|
||||||
};
|
};
|
||||||
use collections::HashMap;
|
|
||||||
use derive_more::{Deref, DerefMut};
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use refineable::Refineable;
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf, sync::Arc, time::Duration,
|
||||||
fmt::Debug,
|
|
||||||
marker::PhantomData,
|
|
||||||
mem,
|
|
||||||
ops::Deref,
|
|
||||||
path::PathBuf,
|
|
||||||
sync::Arc,
|
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const DRAG_THRESHOLD: f64 = 2.;
|
const DRAG_THRESHOLD: f64 = 2.;
|
||||||
const TOOLTIP_DELAY: Duration = Duration::from_millis(500);
|
const TOOLTIP_DELAY: Duration = Duration::from_millis(500);
|
||||||
const TOOLTIP_OFFSET: Point<Pixels> = Point::new(px(10.0), px(8.0));
|
const TOOLTIP_OFFSET: Point<Pixels> = Point::new(px(10.0), px(8.0));
|
||||||
|
|
||||||
pub trait StatelessInteractive<V: 'static>: Element<V> {
|
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V>;
|
|
||||||
|
|
||||||
fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity().hover_style = f(StyleRefinement::default());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn group_hover(
|
|
||||||
mut self,
|
|
||||||
group_name: impl Into<SharedString>,
|
|
||||||
f: impl FnOnce(StyleRefinement) -> StyleRefinement,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity().group_hover_style = Some(GroupStyle {
|
|
||||||
group: group_name.into(),
|
|
||||||
style: f(StyleRefinement::default()),
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_mouse_down(
|
|
||||||
mut self,
|
|
||||||
button: MouseButton,
|
|
||||||
handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.mouse_down_listeners
|
|
||||||
.push(Box::new(move |view, event, bounds, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble
|
|
||||||
&& event.button == button
|
|
||||||
&& bounds.contains_point(&event.position)
|
|
||||||
{
|
|
||||||
handler(view, event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_mouse_up(
|
|
||||||
mut self,
|
|
||||||
button: MouseButton,
|
|
||||||
handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.mouse_up_listeners
|
|
||||||
.push(Box::new(move |view, event, bounds, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble
|
|
||||||
&& event.button == button
|
|
||||||
&& bounds.contains_point(&event.position)
|
|
||||||
{
|
|
||||||
handler(view, event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_mouse_down_out(
|
|
||||||
mut self,
|
|
||||||
handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.mouse_down_listeners
|
|
||||||
.push(Box::new(move |view, event, bounds, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Capture && !bounds.contains_point(&event.position) {
|
|
||||||
handler(view, event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_mouse_up_out(
|
|
||||||
mut self,
|
|
||||||
button: MouseButton,
|
|
||||||
handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.mouse_up_listeners
|
|
||||||
.push(Box::new(move |view, event, bounds, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Capture
|
|
||||||
&& event.button == button
|
|
||||||
&& !bounds.contains_point(&event.position)
|
|
||||||
{
|
|
||||||
handler(view, event, cx);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_mouse_move(
|
|
||||||
mut self,
|
|
||||||
handler: impl Fn(&mut V, &MouseMoveEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.mouse_move_listeners
|
|
||||||
.push(Box::new(move |view, event, bounds, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
|
||||||
handler(view, event, cx);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_scroll_wheel(
|
|
||||||
mut self,
|
|
||||||
handler: impl Fn(&mut V, &ScrollWheelEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.scroll_wheel_listeners
|
|
||||||
.push(Box::new(move |view, event, bounds, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
|
||||||
handler(view, event, cx);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Capture the given action, fires during the capture phase
|
|
||||||
fn capture_action<A: Action>(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &A, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity().action_listeners.push((
|
|
||||||
TypeId::of::<A>(),
|
|
||||||
Box::new(move |view, action, phase, cx| {
|
|
||||||
let action = action.downcast_ref().unwrap();
|
|
||||||
if phase == DispatchPhase::Capture {
|
|
||||||
listener(view, action, cx)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a listener for the given action, fires during the bubble event phase
|
|
||||||
fn on_action<A: Action>(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &A, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity().action_listeners.push((
|
|
||||||
TypeId::of::<A>(),
|
|
||||||
Box::new(move |view, action, phase, cx| {
|
|
||||||
let action = action.downcast_ref().unwrap();
|
|
||||||
if phase == DispatchPhase::Bubble {
|
|
||||||
listener(view, action, cx)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_key_down(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.key_down_listeners
|
|
||||||
.push(Box::new(move |view, event, phase, cx| {
|
|
||||||
listener(view, event, phase, cx)
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_key_up(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.key_up_listeners
|
|
||||||
.push(Box::new(move |view, event, phase, cx| {
|
|
||||||
listener(view, event, phase, cx)
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn drag_over<S: 'static>(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity()
|
|
||||||
.drag_over_styles
|
|
||||||
.push((TypeId::of::<S>(), f(StyleRefinement::default())));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn group_drag_over<S: 'static>(
|
|
||||||
mut self,
|
|
||||||
group_name: impl Into<SharedString>,
|
|
||||||
f: impl FnOnce(StyleRefinement) -> StyleRefinement,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity().group_drag_over_styles.push((
|
|
||||||
TypeId::of::<S>(),
|
|
||||||
GroupStyle {
|
|
||||||
group: group_name.into(),
|
|
||||||
style: f(StyleRefinement::default()),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_drop<W: 'static>(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, View<W>, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateless_interactivity().drop_listeners.push((
|
|
||||||
TypeId::of::<W>(),
|
|
||||||
Box::new(move |view, dragged_view, cx| {
|
|
||||||
listener(view, dragged_view.downcast().unwrap(), cx);
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
|
|
||||||
fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<V>;
|
|
||||||
|
|
||||||
fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateful_interactivity().active_style = f(StyleRefinement::default());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn group_active(
|
|
||||||
mut self,
|
|
||||||
group_name: impl Into<SharedString>,
|
|
||||||
f: impl FnOnce(StyleRefinement) -> StyleRefinement,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateful_interactivity().group_active_style = Some(GroupStyle {
|
|
||||||
group: group_name.into(),
|
|
||||||
style: f(StyleRefinement::default()),
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_click(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &ClickEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateful_interactivity()
|
|
||||||
.click_listeners
|
|
||||||
.push(Box::new(move |view, event, cx| listener(view, event, cx)));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_drag<W>(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &mut ViewContext<V>) -> View<W> + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
W: 'static + Render,
|
|
||||||
{
|
|
||||||
debug_assert!(
|
|
||||||
self.stateful_interactivity().drag_listener.is_none(),
|
|
||||||
"calling on_drag more than once on the same element is not supported"
|
|
||||||
);
|
|
||||||
self.stateful_interactivity().drag_listener =
|
|
||||||
Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag {
|
|
||||||
view: listener(view_state, cx).into(),
|
|
||||||
cursor_offset,
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_hover(mut self, listener: impl 'static + Fn(&mut V, bool, &mut ViewContext<V>)) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
debug_assert!(
|
|
||||||
self.stateful_interactivity().hover_listener.is_none(),
|
|
||||||
"calling on_hover more than once on the same element is not supported"
|
|
||||||
);
|
|
||||||
self.stateful_interactivity().hover_listener = Some(Box::new(listener));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tooltip<W>(
|
|
||||||
mut self,
|
|
||||||
build_tooltip: impl Fn(&mut V, &mut ViewContext<V>) -> View<W> + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
W: 'static + Render,
|
|
||||||
{
|
|
||||||
debug_assert!(
|
|
||||||
self.stateful_interactivity().tooltip_builder.is_none(),
|
|
||||||
"calling tooltip more than once on the same element is not supported"
|
|
||||||
);
|
|
||||||
self.stateful_interactivity().tooltip_builder = Some(Arc::new(move |view_state, cx| {
|
|
||||||
build_tooltip(view_state, cx).into()
|
|
||||||
}));
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ElementInteractivity<V: 'static>: 'static {
|
|
||||||
fn as_stateless(&self) -> &StatelessInteractivity<V>;
|
|
||||||
fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V>;
|
|
||||||
fn as_stateful(&self) -> Option<&StatefulInteractivity<V>>;
|
|
||||||
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>>;
|
|
||||||
|
|
||||||
fn refine_style(
|
|
||||||
&self,
|
|
||||||
style: &mut Style,
|
|
||||||
bounds: Bounds<Pixels>,
|
|
||||||
element_state: &InteractiveElementState,
|
|
||||||
cx: &mut ViewContext<V>,
|
|
||||||
) {
|
|
||||||
let mouse_position = cx.mouse_position();
|
|
||||||
let stateless = self.as_stateless();
|
|
||||||
if let Some(group_hover) = stateless.group_hover_style.as_ref() {
|
|
||||||
if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) {
|
|
||||||
if group_bounds.contains_point(&mouse_position) {
|
|
||||||
style.refine(&group_hover.style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if bounds.contains_point(&mouse_position) {
|
|
||||||
style.refine(&stateless.hover_style);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(drag) = cx.active_drag.take() {
|
|
||||||
for (state_type, group_drag_style) in &self.as_stateless().group_drag_over_styles {
|
|
||||||
if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) {
|
|
||||||
if *state_type == drag.view.entity_type()
|
|
||||||
&& group_bounds.contains_point(&mouse_position)
|
|
||||||
{
|
|
||||||
style.refine(&group_drag_style.style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (state_type, drag_over_style) in &self.as_stateless().drag_over_styles {
|
|
||||||
if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position)
|
|
||||||
{
|
|
||||||
style.refine(drag_over_style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cx.active_drag = Some(drag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(stateful) = self.as_stateful() {
|
|
||||||
let active_state = element_state.active_state.lock();
|
|
||||||
if active_state.group {
|
|
||||||
if let Some(group_style) = stateful.group_active_style.as_ref() {
|
|
||||||
style.refine(&group_style.style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if active_state.element {
|
|
||||||
style.refine(&stateful.active_style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn initialize(&mut self, cx: &mut ViewContext<V>) {
|
|
||||||
let stateless = self.as_stateless_mut();
|
|
||||||
|
|
||||||
for listener in stateless.key_down_listeners.drain(..) {
|
|
||||||
cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| {
|
|
||||||
listener(state, event, phase, cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for listener in stateless.key_up_listeners.drain(..) {
|
|
||||||
cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| {
|
|
||||||
listener(state, event, phase, cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for (action_type, listener) in stateless.action_listeners.drain(..) {
|
|
||||||
cx.on_action(action_type, listener)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_events(
|
|
||||||
&mut self,
|
|
||||||
bounds: Bounds<Pixels>,
|
|
||||||
content_size: Size<Pixels>,
|
|
||||||
overflow: Point<Overflow>,
|
|
||||||
element_state: &mut InteractiveElementState,
|
|
||||||
cx: &mut ViewContext<V>,
|
|
||||||
) {
|
|
||||||
let stateless = self.as_stateless_mut();
|
|
||||||
for listener in stateless.mouse_down_listeners.drain(..) {
|
|
||||||
cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
|
|
||||||
listener(state, event, &bounds, phase, cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for listener in stateless.mouse_up_listeners.drain(..) {
|
|
||||||
cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
|
|
||||||
listener(state, event, &bounds, phase, cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for listener in stateless.mouse_move_listeners.drain(..) {
|
|
||||||
cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
|
|
||||||
listener(state, event, &bounds, phase, cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for listener in stateless.scroll_wheel_listeners.drain(..) {
|
|
||||||
cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
|
|
||||||
listener(state, event, &bounds, phase, cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let hover_group_bounds = stateless
|
|
||||||
.group_hover_style
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|group_hover| GroupBounds::get(&group_hover.group, cx));
|
|
||||||
|
|
||||||
if let Some(group_bounds) = hover_group_bounds {
|
|
||||||
let hovered = group_bounds.contains_point(&cx.mouse_position());
|
|
||||||
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Capture {
|
|
||||||
if group_bounds.contains_point(&event.position) != hovered {
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if stateless.hover_style.is_some()
|
|
||||||
|| (cx.active_drag.is_some() && !stateless.drag_over_styles.is_empty())
|
|
||||||
{
|
|
||||||
let hovered = bounds.contains_point(&cx.mouse_position());
|
|
||||||
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Capture {
|
|
||||||
if bounds.contains_point(&event.position) != hovered {
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if cx.active_drag.is_some() {
|
|
||||||
let drop_listeners = mem::take(&mut stateless.drop_listeners);
|
|
||||||
cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
|
||||||
if let Some(drag_state_type) =
|
|
||||||
cx.active_drag.as_ref().map(|drag| drag.view.entity_type())
|
|
||||||
{
|
|
||||||
for (drop_state_type, listener) in &drop_listeners {
|
|
||||||
if *drop_state_type == drag_state_type {
|
|
||||||
let drag = cx
|
|
||||||
.active_drag
|
|
||||||
.take()
|
|
||||||
.expect("checked for type drag state type above");
|
|
||||||
listener(view, drag.view.clone(), cx);
|
|
||||||
cx.notify();
|
|
||||||
cx.stop_propagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(stateful) = self.as_stateful_mut() {
|
|
||||||
let click_listeners = mem::take(&mut stateful.click_listeners);
|
|
||||||
let drag_listener = mem::take(&mut stateful.drag_listener);
|
|
||||||
|
|
||||||
if !click_listeners.is_empty() || drag_listener.is_some() {
|
|
||||||
let pending_mouse_down = element_state.pending_mouse_down.clone();
|
|
||||||
let mouse_down = pending_mouse_down.lock().clone();
|
|
||||||
if let Some(mouse_down) = mouse_down {
|
|
||||||
if let Some(drag_listener) = drag_listener {
|
|
||||||
let active_state = element_state.active_state.clone();
|
|
||||||
|
|
||||||
cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
|
|
||||||
if cx.active_drag.is_some() {
|
|
||||||
if phase == DispatchPhase::Capture {
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
} else if phase == DispatchPhase::Bubble
|
|
||||||
&& bounds.contains_point(&event.position)
|
|
||||||
&& (event.position - mouse_down.position).magnitude()
|
|
||||||
> DRAG_THRESHOLD
|
|
||||||
{
|
|
||||||
*active_state.lock() = ActiveState::default();
|
|
||||||
let cursor_offset = event.position - bounds.origin;
|
|
||||||
let drag = drag_listener(view_state, cursor_offset, cx);
|
|
||||||
cx.active_drag = Some(drag);
|
|
||||||
cx.notify();
|
|
||||||
cx.stop_propagation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cx.on_mouse_event(move |view_state, event: &MouseUpEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position)
|
|
||||||
{
|
|
||||||
let mouse_click = ClickEvent {
|
|
||||||
down: mouse_down.clone(),
|
|
||||||
up: event.clone(),
|
|
||||||
};
|
|
||||||
for listener in &click_listeners {
|
|
||||||
listener(view_state, &mouse_click, cx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pending_mouse_down.lock() = None;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| {
|
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position)
|
|
||||||
{
|
|
||||||
*pending_mouse_down.lock() = Some(event.clone());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(hover_listener) = stateful.hover_listener.take() {
|
|
||||||
let was_hovered = element_state.hover_state.clone();
|
|
||||||
let has_mouse_down = element_state.pending_mouse_down.clone();
|
|
||||||
|
|
||||||
cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
|
|
||||||
if phase != DispatchPhase::Bubble {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let is_hovered =
|
|
||||||
bounds.contains_point(&event.position) && has_mouse_down.lock().is_none();
|
|
||||||
let mut was_hovered = was_hovered.lock();
|
|
||||||
|
|
||||||
if is_hovered != was_hovered.clone() {
|
|
||||||
*was_hovered = is_hovered;
|
|
||||||
drop(was_hovered);
|
|
||||||
|
|
||||||
hover_listener(view_state, is_hovered, cx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tooltip_builder) = stateful.tooltip_builder.take() {
|
|
||||||
let active_tooltip = element_state.active_tooltip.clone();
|
|
||||||
let pending_mouse_down = element_state.pending_mouse_down.clone();
|
|
||||||
|
|
||||||
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
|
||||||
if phase != DispatchPhase::Bubble {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let is_hovered = bounds.contains_point(&event.position)
|
|
||||||
&& pending_mouse_down.lock().is_none();
|
|
||||||
if !is_hovered {
|
|
||||||
active_tooltip.lock().take();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if active_tooltip.lock().is_none() {
|
|
||||||
let task = cx.spawn({
|
|
||||||
let active_tooltip = active_tooltip.clone();
|
|
||||||
let tooltip_builder = tooltip_builder.clone();
|
|
||||||
|
|
||||||
move |view, mut cx| async move {
|
|
||||||
cx.background_executor().timer(TOOLTIP_DELAY).await;
|
|
||||||
view.update(&mut cx, move |view_state, cx| {
|
|
||||||
active_tooltip.lock().replace(ActiveTooltip {
|
|
||||||
waiting: None,
|
|
||||||
tooltip: Some(AnyTooltip {
|
|
||||||
view: tooltip_builder(view_state, cx),
|
|
||||||
cursor_offset: cx.mouse_position() + TOOLTIP_OFFSET,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
cx.notify();
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
active_tooltip.lock().replace(ActiveTooltip {
|
|
||||||
waiting: Some(task),
|
|
||||||
tooltip: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(active_tooltip) = element_state.active_tooltip.lock().as_ref() {
|
|
||||||
if active_tooltip.tooltip.is_some() {
|
|
||||||
cx.active_tooltip = active_tooltip.tooltip.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let active_state = element_state.active_state.clone();
|
|
||||||
if active_state.lock().is_none() {
|
|
||||||
let active_group_bounds = stateful
|
|
||||||
.group_active_style
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|group_active| GroupBounds::get(&group_active.group, cx));
|
|
||||||
cx.on_mouse_event(move |_view, down: &MouseDownEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble {
|
|
||||||
let group = active_group_bounds
|
|
||||||
.map_or(false, |bounds| bounds.contains_point(&down.position));
|
|
||||||
let element = bounds.contains_point(&down.position);
|
|
||||||
if group || element {
|
|
||||||
*active_state.lock() = ActiveState { group, element };
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Capture {
|
|
||||||
*active_state.lock() = ActiveState::default();
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll {
|
|
||||||
let scroll_offset = element_state
|
|
||||||
.scroll_offset
|
|
||||||
.get_or_insert_with(Arc::default)
|
|
||||||
.clone();
|
|
||||||
let line_height = cx.line_height();
|
|
||||||
let scroll_max = (content_size - bounds.size).max(&Size::default());
|
|
||||||
|
|
||||||
cx.on_mouse_event(move |_, event: &ScrollWheelEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
|
||||||
let mut scroll_offset = scroll_offset.lock();
|
|
||||||
let old_scroll_offset = *scroll_offset;
|
|
||||||
let delta = event.delta.pixel_delta(line_height);
|
|
||||||
|
|
||||||
if overflow.x == Overflow::Scroll {
|
|
||||||
scroll_offset.x =
|
|
||||||
(scroll_offset.x + delta.x).clamp(-scroll_max.width, px(0.));
|
|
||||||
}
|
|
||||||
|
|
||||||
if overflow.y == Overflow::Scroll {
|
|
||||||
scroll_offset.y =
|
|
||||||
(scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.));
|
|
||||||
}
|
|
||||||
|
|
||||||
if *scroll_offset != old_scroll_offset {
|
|
||||||
cx.notify();
|
|
||||||
cx.stop_propagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
|
||||||
pub struct StatefulInteractivity<V> {
|
|
||||||
pub id: ElementId,
|
|
||||||
#[deref]
|
|
||||||
#[deref_mut]
|
|
||||||
stateless: StatelessInteractivity<V>,
|
|
||||||
click_listeners: SmallVec<[ClickListener<V>; 2]>,
|
|
||||||
active_style: StyleRefinement,
|
|
||||||
group_active_style: Option<GroupStyle>,
|
|
||||||
drag_listener: Option<DragListener<V>>,
|
|
||||||
hover_listener: Option<HoverListener<V>>,
|
|
||||||
tooltip_builder: Option<TooltipBuilder<V>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: 'static> StatefulInteractivity<V> {
|
|
||||||
pub fn new(id: ElementId, stateless: StatelessInteractivity<V>) -> Self {
|
|
||||||
Self {
|
|
||||||
id,
|
|
||||||
stateless,
|
|
||||||
click_listeners: SmallVec::new(),
|
|
||||||
active_style: StyleRefinement::default(),
|
|
||||||
group_active_style: None,
|
|
||||||
drag_listener: None,
|
|
||||||
hover_listener: None,
|
|
||||||
tooltip_builder: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: 'static> ElementInteractivity<V> for StatefulInteractivity<V> {
|
|
||||||
fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
|
|
||||||
Some(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
|
|
||||||
Some(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_stateless(&self) -> &StatelessInteractivity<V> {
|
|
||||||
&self.stateless
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
|
|
||||||
&mut self.stateless
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type DropListener<V> = dyn Fn(&mut V, AnyView, &mut ViewContext<V>) + 'static;
|
|
||||||
|
|
||||||
pub struct StatelessInteractivity<V> {
|
|
||||||
pub dispatch_context: KeyContext,
|
|
||||||
pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
|
|
||||||
pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
|
|
||||||
pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
|
|
||||||
pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
|
|
||||||
pub key_down_listeners: SmallVec<[KeyDownListener<V>; 2]>,
|
|
||||||
pub key_up_listeners: SmallVec<[KeyUpListener<V>; 2]>,
|
|
||||||
pub action_listeners: SmallVec<[(TypeId, ActionListener<V>); 8]>,
|
|
||||||
pub hover_style: StyleRefinement,
|
|
||||||
pub group_hover_style: Option<GroupStyle>,
|
|
||||||
drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
|
||||||
group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
|
||||||
drop_listeners: SmallVec<[(TypeId, Box<DropListener<V>>); 2]>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V> StatelessInteractivity<V> {
|
|
||||||
pub fn into_stateful(self, id: impl Into<ElementId>) -> StatefulInteractivity<V> {
|
|
||||||
StatefulInteractivity {
|
|
||||||
id: id.into(),
|
|
||||||
stateless: self,
|
|
||||||
click_listeners: SmallVec::new(),
|
|
||||||
drag_listener: None,
|
|
||||||
hover_listener: None,
|
|
||||||
tooltip_builder: None,
|
|
||||||
active_style: StyleRefinement::default(),
|
|
||||||
group_active_style: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct GroupStyle {
|
|
||||||
pub group: SharedString,
|
|
||||||
pub style: StyleRefinement,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
|
|
||||||
|
|
||||||
impl GroupBounds {
|
|
||||||
pub fn get(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
|
|
||||||
cx.default_global::<Self>()
|
|
||||||
.0
|
|
||||||
.get(name)
|
|
||||||
.and_then(|bounds_stack| bounds_stack.last())
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(name: SharedString, bounds: Bounds<Pixels>, cx: &mut AppContext) {
|
|
||||||
cx.default_global::<Self>()
|
|
||||||
.0
|
|
||||||
.entry(name)
|
|
||||||
.or_default()
|
|
||||||
.push(bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(name: &SharedString, cx: &mut AppContext) {
|
|
||||||
cx.default_global::<Self>().0.get_mut(name).unwrap().pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Eq, PartialEq)]
|
|
||||||
struct ActiveState {
|
|
||||||
pub group: bool,
|
|
||||||
pub element: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveState {
|
|
||||||
pub fn is_none(&self) -> bool {
|
|
||||||
!self.group && !self.element
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct InteractiveElementState {
|
|
||||||
active_state: Arc<Mutex<ActiveState>>,
|
|
||||||
hover_state: Arc<Mutex<bool>>,
|
|
||||||
pending_mouse_down: Arc<Mutex<Option<MouseDownEvent>>>,
|
|
||||||
scroll_offset: Option<Arc<Mutex<Point<Pixels>>>>,
|
|
||||||
active_tooltip: Arc<Mutex<Option<ActiveTooltip>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ActiveTooltip {
|
|
||||||
#[allow(unused)] // used to drop the task
|
|
||||||
waiting: Option<Task<()>>,
|
|
||||||
tooltip: Option<AnyTooltip>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InteractiveElementState {
|
|
||||||
pub fn scroll_offset(&self) -> Option<Point<Pixels>> {
|
|
||||||
self.scroll_offset
|
|
||||||
.as_ref()
|
|
||||||
.map(|offset| offset.lock().clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn track_scroll_offset(&mut self) -> Arc<Mutex<Point<Pixels>>> {
|
|
||||||
self.scroll_offset
|
|
||||||
.get_or_insert_with(|| Arc::new(Mutex::new(Default::default())))
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V> Default for StatelessInteractivity<V> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
dispatch_context: KeyContext::default(),
|
|
||||||
mouse_down_listeners: SmallVec::new(),
|
|
||||||
mouse_up_listeners: SmallVec::new(),
|
|
||||||
mouse_move_listeners: SmallVec::new(),
|
|
||||||
scroll_wheel_listeners: SmallVec::new(),
|
|
||||||
key_down_listeners: SmallVec::new(),
|
|
||||||
key_up_listeners: SmallVec::new(),
|
|
||||||
action_listeners: SmallVec::new(),
|
|
||||||
hover_style: StyleRefinement::default(),
|
|
||||||
group_hover_style: None,
|
|
||||||
drag_over_styles: SmallVec::new(),
|
|
||||||
group_drag_over_styles: SmallVec::new(),
|
|
||||||
drop_listeners: SmallVec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: 'static> ElementInteractivity<V> for StatelessInteractivity<V> {
|
|
||||||
fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_stateless(&self) -> &StatelessInteractivity<V> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct KeyDownEvent {
|
pub struct KeyDownEvent {
|
||||||
pub keystroke: Keystroke,
|
pub keystroke: Keystroke,
|
||||||
|
@ -991,10 +93,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl<S, R, V, E> Render for Drag<S, R, V, E> {
|
|
||||||
// // fn render(&mut self, cx: ViewContext<Self>) ->
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
pub enum MouseButton {
|
pub enum MouseButton {
|
||||||
Left,
|
Left,
|
||||||
|
@ -1103,7 +201,7 @@ impl Deref for MouseExitEvent {
|
||||||
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
|
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
|
||||||
|
|
||||||
impl Render for ExternalPaths {
|
impl Render for ExternalPaths {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div() // Intentionally left empty because the platform will render icons for the dragged files
|
div() // Intentionally left empty because the platform will render icons for the dragged files
|
||||||
|
@ -1229,8 +327,8 @@ pub type ActionListener<V> =
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{
|
use crate::{
|
||||||
self as gpui, div, Div, FocusHandle, KeyBinding, Keystroke, ParentElement, Render,
|
self as gpui, div, FocusHandle, InteractiveComponent, KeyBinding, Keystroke, Node,
|
||||||
StatefulInteractivity, StatelessInteractive, TestAppContext, VisualContext,
|
ParentComponent, Render, Stateful, TestAppContext, VisualContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestView {
|
struct TestView {
|
||||||
|
@ -1242,12 +340,12 @@ mod test {
|
||||||
actions!(TestAction);
|
actions!(TestAction);
|
||||||
|
|
||||||
impl Render for TestView {
|
impl Render for TestView {
|
||||||
type Element = Div<Self, StatefulInteractivity<Self>>;
|
type Element = Stateful<Self, Node<Self>>;
|
||||||
|
|
||||||
fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||||
div().id("testview").child(
|
div().id("testview").child(
|
||||||
div()
|
div()
|
||||||
.context("test")
|
.key_context("test")
|
||||||
.track_focus(&self.focus_handle)
|
.track_focus(&self.focus_handle)
|
||||||
.on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true)
|
.on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true)
|
||||||
.on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true),
|
.on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
build_action_from_type, Action, Bounds, DispatchPhase, Element, FocusEvent, FocusHandle,
|
build_action_from_type, Action, Bounds, DispatchPhase, FocusEvent, FocusHandle, FocusId,
|
||||||
FocusId, KeyContext, KeyMatch, Keymap, Keystroke, KeystrokeMatcher, MouseDownEvent, Pixels,
|
KeyContext, KeyMatch, Keymap, Keystroke, KeystrokeMatcher, MouseDownEvent, Pixels, Style,
|
||||||
Style, StyleRefinement, ViewContext, WindowContext,
|
StyleRefinement, ViewContext, WindowContext,
|
||||||
};
|
};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -342,115 +342,3 @@ impl<V: 'static> KeyDispatch<V> for NonFocusableKeyDispatch {
|
||||||
&mut self.key_context
|
&mut self.key_context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Focusable<V: 'static>: Element<V> {
|
|
||||||
fn focus_listeners(&mut self) -> &mut FocusListeners<V>;
|
|
||||||
fn set_focus_style(&mut self, style: StyleRefinement);
|
|
||||||
fn set_focus_in_style(&mut self, style: StyleRefinement);
|
|
||||||
fn set_in_focus_style(&mut self, style: StyleRefinement);
|
|
||||||
|
|
||||||
fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.set_focus_style(f(StyleRefinement::default()));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.set_focus_in_style(f(StyleRefinement::default()));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.set_in_focus_style(f(StyleRefinement::default()));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_focus(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.focus_listeners()
|
|
||||||
.push(Box::new(move |view, focus_handle, event, cx| {
|
|
||||||
if event.focused.as_ref() == Some(focus_handle) {
|
|
||||||
listener(view, event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_blur(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.focus_listeners()
|
|
||||||
.push(Box::new(move |view, focus_handle, event, cx| {
|
|
||||||
if event.blurred.as_ref() == Some(focus_handle) {
|
|
||||||
listener(view, event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_focus_in(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.focus_listeners()
|
|
||||||
.push(Box::new(move |view, focus_handle, event, cx| {
|
|
||||||
let descendant_blurred = event
|
|
||||||
.blurred
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |blurred| focus_handle.contains(blurred, cx));
|
|
||||||
let descendant_focused = event
|
|
||||||
.focused
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |focused| focus_handle.contains(focused, cx));
|
|
||||||
|
|
||||||
if !descendant_blurred && descendant_focused {
|
|
||||||
listener(view, event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_focus_out(
|
|
||||||
mut self,
|
|
||||||
listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.focus_listeners()
|
|
||||||
.push(Box::new(move |view, focus_handle, event, cx| {
|
|
||||||
let descendant_blurred = event
|
|
||||||
.blurred
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |blurred| focus_handle.contains(blurred, cx));
|
|
||||||
let descendant_focused = event
|
|
||||||
.focused
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |focused| focus_handle.contains(focused, cx));
|
|
||||||
if descendant_blurred && !descendant_focused {
|
|
||||||
listener(view, event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
pub use crate::{Context, ParentElement, Refineable};
|
pub use crate::{
|
||||||
|
BorrowAppContext, BorrowWindow, Component, Context, FocusableComponent, InteractiveComponent,
|
||||||
|
ParentComponent, Refineable, Render, StatefulInteractiveComponent, Styled, VisualContext,
|
||||||
|
};
|
||||||
|
|
|
@ -6,21 +6,20 @@ use crate::{
|
||||||
use crate::{BoxShadow, TextStyleRefinement};
|
use crate::{BoxShadow, TextStyleRefinement};
|
||||||
use refineable::Refineable;
|
use refineable::Refineable;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
use taffy::style::Overflow;
|
||||||
|
|
||||||
pub trait Styled {
|
pub trait Styled: Sized {
|
||||||
fn style(&mut self) -> &mut StyleRefinement;
|
fn style(&mut self) -> &mut StyleRefinement;
|
||||||
|
|
||||||
fn computed_style(&mut self) -> Style {
|
|
||||||
Style::default().refined(self.style().clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
gpui2_macros::style_helpers!();
|
gpui2_macros::style_helpers!();
|
||||||
|
|
||||||
|
fn z_index(mut self, z_index: u32) -> Self {
|
||||||
|
self.style().z_index = Some(z_index);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the size of the element to the full width and height.
|
/// Sets the size of the element to the full width and height.
|
||||||
fn full(mut self) -> Self
|
fn full(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().size.width = Some(relative(1.).into());
|
self.style().size.width = Some(relative(1.).into());
|
||||||
self.style().size.height = Some(relative(1.).into());
|
self.style().size.height = Some(relative(1.).into());
|
||||||
self
|
self
|
||||||
|
@ -28,118 +27,98 @@ pub trait Styled {
|
||||||
|
|
||||||
/// Sets the position of the element to `relative`.
|
/// Sets the position of the element to `relative`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/position)
|
/// [Docs](https://tailwindcss.com/docs/position)
|
||||||
fn relative(mut self) -> Self
|
fn relative(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().position = Some(Position::Relative);
|
self.style().position = Some(Position::Relative);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the position of the element to `absolute`.
|
/// Sets the position of the element to `absolute`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/position)
|
/// [Docs](https://tailwindcss.com/docs/position)
|
||||||
fn absolute(mut self) -> Self
|
fn absolute(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().position = Some(Position::Absolute);
|
self.style().position = Some(Position::Absolute);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the display type of the element to `block`.
|
/// Sets the display type of the element to `block`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/display)
|
/// [Docs](https://tailwindcss.com/docs/display)
|
||||||
fn block(mut self) -> Self
|
fn block(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().display = Some(Display::Block);
|
self.style().display = Some(Display::Block);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the display type of the element to `flex`.
|
/// Sets the display type of the element to `flex`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/display)
|
/// [Docs](https://tailwindcss.com/docs/display)
|
||||||
fn flex(mut self) -> Self
|
fn flex(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().display = Some(Display::Flex);
|
self.style().display = Some(Display::Flex);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the visibility of the element to `visible`.
|
/// Sets the visibility of the element to `visible`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/visibility)
|
/// [Docs](https://tailwindcss.com/docs/visibility)
|
||||||
fn visible(mut self) -> Self
|
fn visible(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().visibility = Some(Visibility::Visible);
|
self.style().visibility = Some(Visibility::Visible);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the visibility of the element to `hidden`.
|
/// Sets the visibility of the element to `hidden`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/visibility)
|
/// [Docs](https://tailwindcss.com/docs/visibility)
|
||||||
fn invisible(mut self) -> Self
|
fn invisible(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().visibility = Some(Visibility::Hidden);
|
self.style().visibility = Some(Visibility::Hidden);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor(mut self, cursor: CursorStyle) -> Self
|
fn overflow_hidden(mut self) -> Self {
|
||||||
where
|
self.style().overflow.x = Some(Overflow::Hidden);
|
||||||
Self: Sized,
|
self.style().overflow.y = Some(Overflow::Hidden);
|
||||||
{
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflow_hidden_x(mut self) -> Self {
|
||||||
|
self.style().overflow.x = Some(Overflow::Hidden);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflow_hidden_y(mut self) -> Self {
|
||||||
|
self.style().overflow.y = Some(Overflow::Hidden);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cursor(mut self, cursor: CursorStyle) -> Self {
|
||||||
self.style().mouse_cursor = Some(cursor);
|
self.style().mouse_cursor = Some(cursor);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the cursor style when hovering an element to `default`.
|
/// Sets the cursor style when hovering an element to `default`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/cursor)
|
/// [Docs](https://tailwindcss.com/docs/cursor)
|
||||||
fn cursor_default(mut self) -> Self
|
fn cursor_default(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().mouse_cursor = Some(CursorStyle::Arrow);
|
self.style().mouse_cursor = Some(CursorStyle::Arrow);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the cursor style when hovering an element to `pointer`.
|
/// Sets the cursor style when hovering an element to `pointer`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/cursor)
|
/// [Docs](https://tailwindcss.com/docs/cursor)
|
||||||
fn cursor_pointer(mut self) -> Self
|
fn cursor_pointer(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().mouse_cursor = Some(CursorStyle::PointingHand);
|
self.style().mouse_cursor = Some(CursorStyle::PointingHand);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the flex direction of the element to `column`.
|
/// Sets the flex direction of the element to `column`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/flex-direction#column)
|
/// [Docs](https://tailwindcss.com/docs/flex-direction#column)
|
||||||
fn flex_col(mut self) -> Self
|
fn flex_col(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().flex_direction = Some(FlexDirection::Column);
|
self.style().flex_direction = Some(FlexDirection::Column);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the flex direction of the element to `row`.
|
/// Sets the flex direction of the element to `row`.
|
||||||
/// [Docs](https://tailwindcss.com/docs/flex-direction#row)
|
/// [Docs](https://tailwindcss.com/docs/flex-direction#row)
|
||||||
fn flex_row(mut self) -> Self
|
fn flex_row(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().flex_direction = Some(FlexDirection::Row);
|
self.style().flex_direction = Some(FlexDirection::Row);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the element to allow a flex item to grow and shrink as needed, ignoring its initial size.
|
/// Sets the element to allow a flex item to grow and shrink as needed, ignoring its initial size.
|
||||||
/// [Docs](https://tailwindcss.com/docs/flex#flex-1)
|
/// [Docs](https://tailwindcss.com/docs/flex#flex-1)
|
||||||
fn flex_1(mut self) -> Self
|
fn flex_1(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().flex_grow = Some(1.);
|
self.style().flex_grow = Some(1.);
|
||||||
self.style().flex_shrink = Some(1.);
|
self.style().flex_shrink = Some(1.);
|
||||||
self.style().flex_basis = Some(relative(0.).into());
|
self.style().flex_basis = Some(relative(0.).into());
|
||||||
|
@ -148,10 +127,7 @@ pub trait Styled {
|
||||||
|
|
||||||
/// Sets the element to allow a flex item to grow and shrink, taking into account its initial size.
|
/// Sets the element to allow a flex item to grow and shrink, taking into account its initial size.
|
||||||
/// [Docs](https://tailwindcss.com/docs/flex#auto)
|
/// [Docs](https://tailwindcss.com/docs/flex#auto)
|
||||||
fn flex_auto(mut self) -> Self
|
fn flex_auto(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().flex_grow = Some(1.);
|
self.style().flex_grow = Some(1.);
|
||||||
self.style().flex_shrink = Some(1.);
|
self.style().flex_shrink = Some(1.);
|
||||||
self.style().flex_basis = Some(Length::Auto);
|
self.style().flex_basis = Some(Length::Auto);
|
||||||
|
@ -160,10 +136,7 @@ pub trait Styled {
|
||||||
|
|
||||||
/// Sets the element to allow a flex item to shrink but not grow, taking into account its initial size.
|
/// Sets the element to allow a flex item to shrink but not grow, taking into account its initial size.
|
||||||
/// [Docs](https://tailwindcss.com/docs/flex#initial)
|
/// [Docs](https://tailwindcss.com/docs/flex#initial)
|
||||||
fn flex_initial(mut self) -> Self
|
fn flex_initial(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().flex_grow = Some(0.);
|
self.style().flex_grow = Some(0.);
|
||||||
self.style().flex_shrink = Some(1.);
|
self.style().flex_shrink = Some(1.);
|
||||||
self.style().flex_basis = Some(Length::Auto);
|
self.style().flex_basis = Some(Length::Auto);
|
||||||
|
@ -172,10 +145,7 @@ pub trait Styled {
|
||||||
|
|
||||||
/// Sets the element to prevent a flex item from growing or shrinking.
|
/// Sets the element to prevent a flex item from growing or shrinking.
|
||||||
/// [Docs](https://tailwindcss.com/docs/flex#none)
|
/// [Docs](https://tailwindcss.com/docs/flex#none)
|
||||||
fn flex_none(mut self) -> Self
|
fn flex_none(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().flex_grow = Some(0.);
|
self.style().flex_grow = Some(0.);
|
||||||
self.style().flex_shrink = Some(0.);
|
self.style().flex_shrink = Some(0.);
|
||||||
self
|
self
|
||||||
|
@ -183,40 +153,28 @@ pub trait Styled {
|
||||||
|
|
||||||
/// Sets the element to allow a flex item to grow to fill any available space.
|
/// Sets the element to allow a flex item to grow to fill any available space.
|
||||||
/// [Docs](https://tailwindcss.com/docs/flex-grow)
|
/// [Docs](https://tailwindcss.com/docs/flex-grow)
|
||||||
fn grow(mut self) -> Self
|
fn grow(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().flex_grow = Some(1.);
|
self.style().flex_grow = Some(1.);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the element to align flex items to the start of the container's cross axis.
|
/// Sets the element to align flex items to the start of the container's cross axis.
|
||||||
/// [Docs](https://tailwindcss.com/docs/align-items#start)
|
/// [Docs](https://tailwindcss.com/docs/align-items#start)
|
||||||
fn items_start(mut self) -> Self
|
fn items_start(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().align_items = Some(AlignItems::FlexStart);
|
self.style().align_items = Some(AlignItems::FlexStart);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the element to align flex items to the end of the container's cross axis.
|
/// Sets the element to align flex items to the end of the container's cross axis.
|
||||||
/// [Docs](https://tailwindcss.com/docs/align-items#end)
|
/// [Docs](https://tailwindcss.com/docs/align-items#end)
|
||||||
fn items_end(mut self) -> Self
|
fn items_end(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().align_items = Some(AlignItems::FlexEnd);
|
self.style().align_items = Some(AlignItems::FlexEnd);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the element to align flex items along the center of the container's cross axis.
|
/// Sets the element to align flex items along the center of the container's cross axis.
|
||||||
/// [Docs](https://tailwindcss.com/docs/align-items#center)
|
/// [Docs](https://tailwindcss.com/docs/align-items#center)
|
||||||
fn items_center(mut self) -> Self
|
fn items_center(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().align_items = Some(AlignItems::Center);
|
self.style().align_items = Some(AlignItems::Center);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -224,40 +182,28 @@ pub trait Styled {
|
||||||
/// Sets the element to justify flex items along the container's main axis
|
/// Sets the element to justify flex items along the container's main axis
|
||||||
/// such that there is an equal amount of space between each item.
|
/// such that there is an equal amount of space between each item.
|
||||||
/// [Docs](https://tailwindcss.com/docs/justify-content#space-between)
|
/// [Docs](https://tailwindcss.com/docs/justify-content#space-between)
|
||||||
fn justify_between(mut self) -> Self
|
fn justify_between(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().justify_content = Some(JustifyContent::SpaceBetween);
|
self.style().justify_content = Some(JustifyContent::SpaceBetween);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the element to justify flex items along the center of the container's main axis.
|
/// Sets the element to justify flex items along the center of the container's main axis.
|
||||||
/// [Docs](https://tailwindcss.com/docs/justify-content#center)
|
/// [Docs](https://tailwindcss.com/docs/justify-content#center)
|
||||||
fn justify_center(mut self) -> Self
|
fn justify_center(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().justify_content = Some(JustifyContent::Center);
|
self.style().justify_content = Some(JustifyContent::Center);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the element to justify flex items against the start of the container's main axis.
|
/// Sets the element to justify flex items against the start of the container's main axis.
|
||||||
/// [Docs](https://tailwindcss.com/docs/justify-content#start)
|
/// [Docs](https://tailwindcss.com/docs/justify-content#start)
|
||||||
fn justify_start(mut self) -> Self
|
fn justify_start(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().justify_content = Some(JustifyContent::Start);
|
self.style().justify_content = Some(JustifyContent::Start);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the element to justify flex items against the end of the container's main axis.
|
/// Sets the element to justify flex items against the end of the container's main axis.
|
||||||
/// [Docs](https://tailwindcss.com/docs/justify-content#end)
|
/// [Docs](https://tailwindcss.com/docs/justify-content#end)
|
||||||
fn justify_end(mut self) -> Self
|
fn justify_end(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().justify_content = Some(JustifyContent::End);
|
self.style().justify_content = Some(JustifyContent::End);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -265,10 +211,7 @@ pub trait Styled {
|
||||||
/// Sets the element to justify items along the container's main axis such
|
/// Sets the element to justify items along the container's main axis such
|
||||||
/// that there is an equal amount of space on each side of each item.
|
/// that there is an equal amount of space on each side of each item.
|
||||||
/// [Docs](https://tailwindcss.com/docs/justify-content#space-around)
|
/// [Docs](https://tailwindcss.com/docs/justify-content#space-around)
|
||||||
fn justify_around(mut self) -> Self
|
fn justify_around(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().justify_content = Some(JustifyContent::SpaceAround);
|
self.style().justify_content = Some(JustifyContent::SpaceAround);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -295,30 +238,21 @@ pub trait Styled {
|
||||||
|
|
||||||
/// Sets the box shadow of the element.
|
/// Sets the box shadow of the element.
|
||||||
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow(mut self, shadows: SmallVec<[BoxShadow; 2]>) -> Self
|
fn shadow(mut self, shadows: SmallVec<[BoxShadow; 2]>) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().box_shadow = Some(shadows);
|
self.style().box_shadow = Some(shadows);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears the box shadow of the element.
|
/// Clears the box shadow of the element.
|
||||||
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow_none(mut self) -> Self
|
fn shadow_none(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().box_shadow = Some(Default::default());
|
self.style().box_shadow = Some(Default::default());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the box shadow of the element.
|
/// Sets the box shadow of the element.
|
||||||
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow_sm(mut self) -> Self
|
fn shadow_sm(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().box_shadow = Some(smallvec::smallvec
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow_md(mut self) -> Self
|
fn shadow_md(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().box_shadow = Some(smallvec
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow_lg(mut self) -> Self
|
fn shadow_lg(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().box_shadow = Some(smallvec
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow_xl(mut self) -> Self
|
fn shadow_xl(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().box_shadow = Some(smallvec
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow_2xl(mut self) -> Self
|
fn shadow_2xl(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.style().box_shadow = Some(smallvec![BoxShadow {
|
self.style().box_shadow = Some(smallvec![BoxShadow {
|
||||||
color: hsla(0., 0., 0., 0.25),
|
color: hsla(0., 0., 0., 0.25),
|
||||||
offset: point(px(0.), px(25.)),
|
offset: point(px(0.), px(25.)),
|
||||||
|
@ -417,198 +339,138 @@ pub trait Styled {
|
||||||
&mut style.text
|
&mut style.text
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_color(mut self, color: impl Into<Hsla>) -> Self
|
fn text_color(mut self, color: impl Into<Hsla>) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style().get_or_insert_with(Default::default).color = Some(color.into());
|
self.text_style().get_or_insert_with(Default::default).color = Some(color.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self
|
fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(size.into());
|
.font_size = Some(size.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_xs(mut self) -> Self
|
fn text_xs(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(rems(0.75).into());
|
.font_size = Some(rems(0.75).into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_sm(mut self) -> Self
|
fn text_sm(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(rems(0.875).into());
|
.font_size = Some(rems(0.875).into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_base(mut self) -> Self
|
fn text_base(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(rems(1.0).into());
|
.font_size = Some(rems(1.0).into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_lg(mut self) -> Self
|
fn text_lg(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(rems(1.125).into());
|
.font_size = Some(rems(1.125).into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_xl(mut self) -> Self
|
fn text_xl(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(rems(1.25).into());
|
.font_size = Some(rems(1.25).into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_2xl(mut self) -> Self
|
fn text_2xl(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(rems(1.5).into());
|
.font_size = Some(rems(1.5).into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_3xl(mut self) -> Self
|
fn text_3xl(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_size = Some(rems(1.875).into());
|
.font_size = Some(rems(1.875).into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_none(mut self) -> Self
|
fn text_decoration_none(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.underline = None;
|
.underline = None;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_color(mut self, color: impl Into<Hsla>) -> Self
|
fn text_decoration_color(mut self, color: impl Into<Hsla>) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.color = Some(color.into());
|
underline.color = Some(color.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_solid(mut self) -> Self
|
fn text_decoration_solid(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.wavy = false;
|
underline.wavy = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_wavy(mut self) -> Self
|
fn text_decoration_wavy(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.wavy = true;
|
underline.wavy = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_0(mut self) -> Self
|
fn text_decoration_0(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.thickness = px(0.);
|
underline.thickness = px(0.);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_1(mut self) -> Self
|
fn text_decoration_1(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.thickness = px(1.);
|
underline.thickness = px(1.);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_2(mut self) -> Self
|
fn text_decoration_2(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.thickness = px(2.);
|
underline.thickness = px(2.);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_4(mut self) -> Self
|
fn text_decoration_4(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.thickness = px(4.);
|
underline.thickness = px(4.);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_decoration_8(mut self) -> Self
|
fn text_decoration_8(mut self) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let style = self.text_style().get_or_insert_with(Default::default);
|
let style = self.text_style().get_or_insert_with(Default::default);
|
||||||
let underline = style.underline.get_or_insert_with(Default::default);
|
let underline = style.underline.get_or_insert_with(Default::default);
|
||||||
underline.thickness = px(8.);
|
underline.thickness = px(8.);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn font(mut self, family_name: impl Into<SharedString>) -> Self
|
fn font(mut self, family_name: impl Into<SharedString>) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.font_family = Some(family_name.into());
|
.font_family = Some(family_name.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self
|
fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.text_style()
|
self.text_style()
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.line_height = Some(line_height.into());
|
.line_height = Some(line_height.into());
|
||||||
|
|
|
@ -206,7 +206,7 @@ impl<V: Render> From<View<V>> for AnyView {
|
||||||
impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
||||||
type ElementState = Box<dyn Any>;
|
type ElementState = Box<dyn Any>;
|
||||||
|
|
||||||
fn id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
Some(self.model.entity_id.into())
|
Some(self.model.entity_id.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ fn generate_predefined_setter(
|
||||||
|
|
||||||
let method = quote! {
|
let method = quote! {
|
||||||
#[doc = #doc_string]
|
#[doc = #doc_string]
|
||||||
fn #method_name(mut self) -> Self where Self: std::marker::Sized {
|
fn #method_name(mut self) -> Self {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
#(#field_assignments)*
|
#(#field_assignments)*
|
||||||
self
|
self
|
||||||
|
@ -163,7 +163,7 @@ fn generate_custom_value_setter(
|
||||||
|
|
||||||
let method = quote! {
|
let method = quote! {
|
||||||
#[doc = #doc_string]
|
#[doc = #doc_string]
|
||||||
fn #method_name(mut self, length: impl std::clone::Clone + Into<gpui::#length_type>) -> Self where Self: std::marker::Sized {
|
fn #method_name(mut self, length: impl std::clone::Clone + Into<gpui::#length_type>) -> Self {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
#(#field_assignments)*
|
#(#field_assignments)*
|
||||||
self
|
self
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, uniform_list, Component, Div, ParentElement, Render, StatelessInteractive, Styled, Task,
|
div, uniform_list, Component, Node, ParentComponent, Render, Styled, Task,
|
||||||
UniformListScrollHandle, View, ViewContext, VisualContext, WindowContext,
|
UniformListScrollHandle, View, ViewContext, VisualContext, WindowContext,
|
||||||
};
|
};
|
||||||
use std::{cmp, sync::Arc};
|
use std::{cmp, sync::Arc};
|
||||||
|
@ -139,11 +139,11 @@ impl<D: PickerDelegate> Picker<D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: PickerDelegate> Render for Picker<D> {
|
impl<D: PickerDelegate> Render for Picker<D> {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div()
|
div()
|
||||||
.context("picker")
|
.key_context("picker")
|
||||||
.size_full()
|
.size_full()
|
||||||
.elevation_2(cx)
|
.elevation_2(cx)
|
||||||
.on_action(Self::select_next)
|
.on_action(Self::select_next)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::story::Story;
|
use crate::story::Story;
|
||||||
use gpui::{px, Div, Render};
|
use gpui::{prelude::*, px, Node, Render};
|
||||||
use theme2::{default_color_scales, ColorScaleStep};
|
use theme2::{default_color_scales, ColorScaleStep};
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
pub struct ColorsStory;
|
pub struct ColorsStory;
|
||||||
|
|
||||||
impl Render for ColorsStory {
|
impl Render for ColorsStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let color_scales = default_color_scales();
|
let color_scales = default_color_scales();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, Div, FocusHandle, Focusable, FocusableKeyDispatch, KeyBinding, ParentElement,
|
actions, div, prelude::*, FocusHandle, Focusable, KeyBinding, Node, Render, Stateful, View,
|
||||||
Render, StatefulInteractivity, StatelessInteractive, Styled, View, VisualContext,
|
|
||||||
WindowContext,
|
WindowContext,
|
||||||
};
|
};
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
@ -28,7 +27,7 @@ impl FocusStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for FocusStory {
|
impl Render for FocusStory {
|
||||||
type Element = Div<Self, StatefulInteractivity<Self>, FocusableKeyDispatch<Self>>;
|
type Element = Focusable<Self, Stateful<Self, Node<Self>>>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||||
let theme = cx.theme();
|
let theme = cx.theme();
|
||||||
|
@ -42,7 +41,7 @@ impl Render for FocusStory {
|
||||||
div()
|
div()
|
||||||
.id("parent")
|
.id("parent")
|
||||||
.focusable()
|
.focusable()
|
||||||
.context("parent")
|
.key_context("parent")
|
||||||
.on_action(|_, action: &ActionA, cx| {
|
.on_action(|_, action: &ActionA, cx| {
|
||||||
println!("Action A dispatched on parent");
|
println!("Action A dispatched on parent");
|
||||||
})
|
})
|
||||||
|
@ -62,7 +61,7 @@ impl Render for FocusStory {
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.track_focus(&self.child_1_focus)
|
.track_focus(&self.child_1_focus)
|
||||||
.context("child-1")
|
.key_context("child-1")
|
||||||
.on_action(|_, action: &ActionB, cx| {
|
.on_action(|_, action: &ActionB, cx| {
|
||||||
println!("Action B dispatched on child 1 during");
|
println!("Action B dispatched on child 1 during");
|
||||||
})
|
})
|
||||||
|
@ -82,7 +81,7 @@ impl Render for FocusStory {
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.track_focus(&self.child_2_focus)
|
.track_focus(&self.child_2_focus)
|
||||||
.context("child-2")
|
.key_context("child-2")
|
||||||
.on_action(|_, action: &ActionC, cx| {
|
.on_action(|_, action: &ActionC, cx| {
|
||||||
println!("Action C dispatched on child 2");
|
println!("Action C dispatched on child 2");
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{story::Story, story_selector::ComponentStory};
|
use crate::{story::Story, story_selector::ComponentStory};
|
||||||
use gpui::{Div, Render, StatefulInteractivity, View, VisualContext};
|
use gpui::{prelude::*, Node, Render, Stateful, View};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ impl KitchenSinkStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for KitchenSinkStory {
|
impl Render for KitchenSinkStory {
|
||||||
type Element = Div<Self, StatefulInteractivity<Self>>;
|
type Element = Stateful<Self, Node<Self>>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let component_stories = ComponentStory::iter()
|
let component_stories = ComponentStory::iter()
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use fuzzy::StringMatchCandidate;
|
use fuzzy::StringMatchCandidate;
|
||||||
use gpui::{
|
use gpui::{div, prelude::*, KeyBinding, Node, Render, Styled, Task, View, WindowContext};
|
||||||
div, Component, Div, KeyBinding, ParentElement, Render, StatelessInteractive, Styled, Task,
|
|
||||||
View, VisualContext, WindowContext,
|
|
||||||
};
|
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
|
use std::sync::Arc;
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
|
||||||
pub struct PickerStory {
|
pub struct PickerStory {
|
||||||
|
@ -38,7 +34,7 @@ impl Delegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for Delegate {
|
impl PickerDelegate for Delegate {
|
||||||
type ListItem = Div<Picker<Self>>;
|
type ListItem = Node<Picker<Self>>;
|
||||||
|
|
||||||
fn match_count(&self) -> usize {
|
fn match_count(&self) -> usize {
|
||||||
self.candidates.len()
|
self.candidates.len()
|
||||||
|
@ -207,7 +203,7 @@ impl PickerStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for PickerStory {
|
impl Render for PickerStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||||
div()
|
div()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, px, Component, Div, ParentElement, Render, SharedString, StatefulInteractivity, Styled,
|
div, prelude::*, px, Node, Render, SharedString, Stateful, Styled, View, WindowContext,
|
||||||
View, VisualContext, WindowContext,
|
|
||||||
};
|
};
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ impl ScrollStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for ScrollStory {
|
impl Render for ScrollStory {
|
||||||
type Element = Div<Self, StatefulInteractivity<Self>>;
|
type Element = Stateful<Self, Node<Self>>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||||
let theme = cx.theme();
|
let theme = cx.theme();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{div, white, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext};
|
use gpui::{div, white, Node, ParentComponent, Render, Styled, View, VisualContext, WindowContext};
|
||||||
|
|
||||||
pub struct TextStory;
|
pub struct TextStory;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ impl TextStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for TextStory {
|
impl Render for TextStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||||
div().size_full().bg(white()).child(concat!(
|
div().size_full().bg(white()).child(concat!(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{px, rgb, Div, Hsla, Render};
|
use gpui::{px, rgb, Hsla, Node, Render};
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
use crate::story::Story;
|
use crate::story::Story;
|
||||||
|
@ -8,7 +8,7 @@ use crate::story::Story;
|
||||||
pub struct ZIndexStory;
|
pub struct ZIndexStory;
|
||||||
|
|
||||||
impl Render for ZIndexStory {
|
impl Render for ZIndexStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
@ -77,7 +77,7 @@ trait Styles: Styled + Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Styles for Div<V> {}
|
impl<V: 'static> Styles for Node<V> {}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct ZIndexExample {
|
struct ZIndexExample {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, px, size, AnyView, AppContext, Bounds, Div, Render, ViewContext, VisualContext,
|
div, px, size, AnyView, AppContext, Bounds, Node, Render, ViewContext, VisualContext,
|
||||||
WindowBounds, WindowOptions,
|
WindowBounds, WindowOptions,
|
||||||
};
|
};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
@ -107,7 +107,7 @@ impl StoryWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for StoryWrapper {
|
impl Render for StoryWrapper {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div()
|
div()
|
||||||
|
|
|
@ -40,12 +40,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{ActiveTheme, Story};
|
use crate::{ActiveTheme, Story};
|
||||||
use gpui::{div, img, px, Div, ParentElement, Render, Styled, ViewContext};
|
use gpui::{div, img, px, Node, ParentComponent, Render, Styled, ViewContext};
|
||||||
|
|
||||||
pub struct PlayerStory;
|
pub struct PlayerStory;
|
||||||
|
|
||||||
impl Render for PlayerStory {
|
impl Render for PlayerStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx).child(
|
Story::container(cx).child(
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use gpui::{div, Component, Div, ParentElement, Styled, ViewContext};
|
use gpui::{div, Component, Node, ParentComponent, Styled, ViewContext};
|
||||||
|
|
||||||
use crate::ActiveTheme;
|
use crate::ActiveTheme;
|
||||||
|
|
||||||
pub struct Story {}
|
pub struct Story {}
|
||||||
|
|
||||||
impl Story {
|
impl Story {
|
||||||
pub fn container<V: 'static>(cx: &mut ViewContext<V>) -> Div<V> {
|
pub fn container<V: 'static>(cx: &mut ViewContext<V>) -> Node<V> {
|
||||||
div()
|
div()
|
||||||
.size_full()
|
.size_full()
|
||||||
.flex()
|
.flex()
|
||||||
|
|
|
@ -44,12 +44,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct AvatarStory;
|
pub struct AvatarStory;
|
||||||
|
|
||||||
impl Render for AvatarStory {
|
impl Render for AvatarStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gpui::{div, DefiniteLength, Hsla, MouseButton, WindowContext};
|
use gpui::{div, DefiniteLength, Hsla, MouseButton, StatefulInteractiveComponent, WindowContext};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
h_stack, prelude::*, Icon, IconButton, IconColor, IconElement, Label, LabelColor,
|
h_stack, prelude::*, Icon, IconButton, IconColor, IconElement, Label, LabelColor,
|
||||||
|
@ -236,13 +236,13 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{h_stack, v_stack, LabelColor, Story};
|
use crate::{h_stack, v_stack, LabelColor, Story};
|
||||||
use gpui::{rems, Div, Render};
|
use gpui::{rems, Node, Render};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
pub struct ButtonStory;
|
pub struct ButtonStory;
|
||||||
|
|
||||||
impl Render for ButtonStory {
|
impl Render for ButtonStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let states = InteractionState::iter();
|
let states = InteractionState::iter();
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
|
use gpui::{div, prelude::*, Component, ElementId, Styled, ViewContext};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gpui::{
|
|
||||||
div, Component, ElementId, ParentElement, StatefulInteractive, StatelessInteractive, Styled,
|
|
||||||
ViewContext,
|
|
||||||
};
|
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
|
||||||
use crate::{Icon, IconColor, IconElement, Selection};
|
use crate::{Icon, IconColor, IconElement, Selection};
|
||||||
|
@ -175,12 +171,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{h_stack, Story};
|
use crate::{h_stack, Story};
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct CheckboxStory;
|
pub struct CheckboxStory;
|
||||||
|
|
||||||
impl Render for CheckboxStory {
|
impl Render for CheckboxStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -65,12 +65,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::story::Story;
|
use crate::story::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct ContextMenuStory;
|
pub struct ContextMenuStory;
|
||||||
|
|
||||||
impl Render for ContextMenuStory {
|
impl Render for ContextMenuStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -47,12 +47,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{Button, Story};
|
use crate::{Button, Story};
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct DetailsStory;
|
pub struct DetailsStory;
|
||||||
|
|
||||||
impl Render for DetailsStory {
|
impl Render for DetailsStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use gpui::Div;
|
use gpui::Node;
|
||||||
|
|
||||||
use crate::{prelude::*, v_stack};
|
use crate::{prelude::*, v_stack};
|
||||||
|
|
||||||
/// Create an elevated surface.
|
/// Create an elevated surface.
|
||||||
///
|
///
|
||||||
/// Must be used inside of a relative parent element
|
/// Must be used inside of a relative parent element
|
||||||
pub fn elevated_surface<V: 'static>(level: ElevationIndex, cx: &mut ViewContext<V>) -> Div<V> {
|
pub fn elevated_surface<V: 'static>(level: ElevationIndex, cx: &mut ViewContext<V>) -> Node<V> {
|
||||||
let colors = cx.theme().colors();
|
let colors = cx.theme().colors();
|
||||||
|
|
||||||
// let shadow = BoxShadow {
|
// let shadow = BoxShadow {
|
||||||
|
@ -23,6 +23,6 @@ pub fn elevated_surface<V: 'static>(level: ElevationIndex, cx: &mut ViewContext<
|
||||||
.shadow(level.shadow())
|
.shadow(level.shadow())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn modal<V>(cx: &mut ViewContext<V>) -> Div<V> {
|
pub fn modal<V: 'static>(cx: &mut ViewContext<V>) -> Node<V> {
|
||||||
elevated_surface(ElevationIndex::ModalSurface, cx)
|
elevated_surface(ElevationIndex::ModalSurface, cx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,12 +33,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{static_players, Story};
|
use crate::{static_players, Story};
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct FacepileStory;
|
pub struct FacepileStory;
|
||||||
|
|
||||||
impl Render for FacepileStory {
|
impl Render for FacepileStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let players = static_players();
|
let players = static_players();
|
||||||
|
|
|
@ -204,7 +204,7 @@ pub use stories::*;
|
||||||
|
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
|
@ -214,7 +214,7 @@ mod stories {
|
||||||
pub struct IconStory;
|
pub struct IconStory;
|
||||||
|
|
||||||
impl Render for IconStory {
|
impl Render for IconStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let icons = Icon::iter();
|
let icons = Icon::iter();
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use gpui::{rems, MouseButton};
|
|
||||||
|
|
||||||
use crate::{h_stack, prelude::*};
|
use crate::{h_stack, prelude::*};
|
||||||
use crate::{ClickHandler, Icon, IconColor, IconElement};
|
use crate::{ClickHandler, Icon, IconColor, IconElement};
|
||||||
|
use gpui::{prelude::*, rems, MouseButton};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
struct IconButtonHandlers<V: 'static> {
|
struct IconButtonHandlers<V: 'static> {
|
||||||
click: Option<ClickHandler<V>>,
|
click: Option<ClickHandler<V>>,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::prelude::*;
|
use crate::{prelude::*, Label, LabelColor};
|
||||||
use crate::Label;
|
use gpui::prelude::*;
|
||||||
use crate::LabelColor;
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq)]
|
#[derive(Default, PartialEq)]
|
||||||
pub enum InputVariant {
|
pub enum InputVariant {
|
||||||
|
@ -111,12 +110,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct InputStory;
|
pub struct InputStory;
|
||||||
|
|
||||||
impl Render for InputStory {
|
impl Render for InputStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -158,13 +158,13 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
pub struct KeybindingStory;
|
pub struct KeybindingStory;
|
||||||
|
|
||||||
impl Render for KeybindingStory {
|
impl Render for KeybindingStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let all_modifier_permutations = ModifierKey::iter().permutations(2);
|
let all_modifier_permutations = ModifierKey::iter().permutations(2);
|
||||||
|
|
|
@ -196,12 +196,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct LabelStory;
|
pub struct LabelStory;
|
||||||
|
|
||||||
impl Render for LabelStory {
|
impl Render for LabelStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl<V: 'static> Modal<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> ParentElement<V> for Modal<V> {
|
impl<V: 'static> ParentComponent<V> for Modal<V> {
|
||||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
&mut self.children
|
&mut self.children
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::prelude::*;
|
use crate::{h_stack, prelude::*, v_stack, Keybinding, Label, LabelColor};
|
||||||
use crate::{h_stack, v_stack, Keybinding, Label, LabelColor};
|
use gpui::prelude::*;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Palette {
|
pub struct Palette {
|
||||||
|
@ -159,7 +159,7 @@ pub use stories::*;
|
||||||
|
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::{ModifierKeys, Story};
|
use crate::{ModifierKeys, Story};
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ mod stories {
|
||||||
pub struct PaletteStory;
|
pub struct PaletteStory;
|
||||||
|
|
||||||
impl Render for PaletteStory {
|
impl Render for PaletteStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{AbsoluteLength, AnyElement};
|
use gpui::{prelude::*, AbsoluteLength, AnyElement};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -113,7 +113,7 @@ impl<V: 'static> Panel<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> ParentElement<V> for Panel<V> {
|
impl<V: 'static> ParentComponent<V> for Panel<V> {
|
||||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
&mut self.children
|
&mut self.children
|
||||||
}
|
}
|
||||||
|
@ -126,12 +126,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{Label, Story};
|
use crate::{Label, Story};
|
||||||
use gpui::{Div, Render};
|
use gpui::{InteractiveComponent, Node, Render};
|
||||||
|
|
||||||
pub struct PanelStory;
|
pub struct PanelStory;
|
||||||
|
|
||||||
impl Render for PanelStory {
|
impl Render for PanelStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use gpui::{div, Div};
|
use gpui::{div, Node};
|
||||||
|
|
||||||
use crate::StyledExt;
|
use crate::StyledExt;
|
||||||
|
|
||||||
/// Horizontally stacks elements.
|
/// Horizontally stacks elements.
|
||||||
///
|
///
|
||||||
/// Sets `flex()`, `flex_row()`, `items_center()`
|
/// Sets `flex()`, `flex_row()`, `items_center()`
|
||||||
pub fn h_stack<V: 'static>() -> Div<V> {
|
pub fn h_stack<V: 'static>() -> Node<V> {
|
||||||
div().h_flex()
|
div().h_flex()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vertically stacks elements.
|
/// Vertically stacks elements.
|
||||||
///
|
///
|
||||||
/// Sets `flex()`, `flex_col()`
|
/// Sets `flex()`, `flex_col()`
|
||||||
pub fn v_stack<V: 'static>() -> Div<V> {
|
pub fn v_stack<V: 'static>() -> Node<V> {
|
||||||
div().v_flex()
|
div().v_flex()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{Icon, IconColor, IconElement, Label, LabelColor};
|
use crate::{Icon, IconColor, IconElement, Label, LabelColor};
|
||||||
use gpui::{red, Div, ElementId, Render, View, VisualContext};
|
use gpui::{prelude::*, red, ElementId, Node, Render, View};
|
||||||
|
|
||||||
#[derive(Component, Clone)]
|
#[derive(Component, Clone)]
|
||||||
pub struct Tab {
|
pub struct Tab {
|
||||||
|
@ -21,7 +21,7 @@ struct TabDragState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for TabDragState {
|
impl Render for TabDragState {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div().w_8().h_4().bg(red())
|
div().w_8().h_4().bg(red())
|
||||||
|
@ -178,7 +178,7 @@ mod stories {
|
||||||
pub struct TabStory;
|
pub struct TabStory;
|
||||||
|
|
||||||
impl Render for TabStory {
|
impl Render for TabStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let git_statuses = GitStatus::iter();
|
let git_statuses = GitStatus::iter();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use gpui::AnyElement;
|
|
||||||
use smallvec::SmallVec;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use gpui::{prelude::*, AnyElement};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum ToastOrigin {
|
pub enum ToastOrigin {
|
||||||
|
@ -59,7 +58,7 @@ impl<V: 'static> Toast<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> ParentElement<V> for Toast<V> {
|
impl<V: 'static> ParentComponent<V> for Toast<V> {
|
||||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
&mut self.children
|
&mut self.children
|
||||||
}
|
}
|
||||||
|
@ -70,7 +69,7 @@ pub use stories::*;
|
||||||
|
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::{Label, Story};
|
use crate::{Label, Story};
|
||||||
|
|
||||||
|
@ -79,7 +78,7 @@ mod stories {
|
||||||
pub struct ToastStory;
|
pub struct ToastStory;
|
||||||
|
|
||||||
impl Render for ToastStory {
|
impl Render for ToastStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{div, Component, ParentElement};
|
use gpui::{div, Component, ParentComponent};
|
||||||
|
|
||||||
use crate::{Icon, IconColor, IconElement, IconSize};
|
use crate::{Icon, IconColor, IconElement, IconSize};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{div, Div, ParentElement, Render, SharedString, Styled, ViewContext};
|
use gpui::{div, Node, ParentComponent, Render, SharedString, Styled, ViewContext};
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -13,7 +13,7 @@ impl TextTooltip {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for TextTooltip {
|
impl Render for TextTooltip {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let theme = cx.theme();
|
let theme = cx.theme();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use gpui::rems;
|
use gpui::rems;
|
||||||
use gpui::Rems;
|
use gpui::Rems;
|
||||||
pub use gpui::{
|
pub use gpui::{
|
||||||
div, Component, Element, ElementId, ParentElement, SharedString, StatefulInteractive,
|
div, Component, Element, ElementId, InteractiveComponent, ParentComponent, SharedString, Styled,
|
||||||
StatelessInteractive, Styled, ViewContext, WindowContext,
|
ViewContext, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::elevation::*;
|
pub use crate::elevation::*;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use gpui::Div;
|
use gpui::Node;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Story {}
|
pub struct Story {}
|
||||||
|
|
||||||
impl Story {
|
impl Story {
|
||||||
pub fn container<V: 'static>(cx: &mut ViewContext<V>) -> Div<V> {
|
pub fn container<V: 'static>(cx: &mut ViewContext<V>) -> Node<V> {
|
||||||
div()
|
div()
|
||||||
.size_full()
|
.size_full()
|
||||||
.flex()
|
.flex()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{Div, ElementInteractivity, KeyDispatch, Styled, UniformList, ViewContext};
|
use gpui::{Styled, ViewContext};
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
|
||||||
use crate::{ElevationIndex, UITextSize};
|
use crate::{ElevationIndex, UITextSize};
|
||||||
|
@ -93,11 +93,4 @@ pub trait StyledExt: Styled + Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, I, F> StyledExt for Div<V, I, F>
|
impl<E: Styled> StyledExt for E {}
|
||||||
where
|
|
||||||
I: ElementInteractivity<V>,
|
|
||||||
F: KeyDispatch<V>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V> StyledExt for UniformList<V> {}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{Icon, IconButton, Label, Panel, PanelSide};
|
use crate::{Icon, IconButton, Label, Panel, PanelSide};
|
||||||
use gpui::{rems, AbsoluteLength};
|
use gpui::{prelude::*, rems, AbsoluteLength};
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct AssistantPanel {
|
pub struct AssistantPanel {
|
||||||
|
@ -77,11 +77,11 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
pub struct AssistantPanelStory;
|
pub struct AssistantPanelStory;
|
||||||
|
|
||||||
impl Render for AssistantPanelStory {
|
impl Render for AssistantPanelStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
|
use crate::{h_stack, prelude::*, HighlightedText};
|
||||||
|
use gpui::{prelude::*, Node};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::{h_stack, HighlightedText};
|
|
||||||
use gpui::Div;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Symbol(pub Vec<HighlightedText>);
|
pub struct Symbol(pub Vec<HighlightedText>);
|
||||||
|
|
||||||
|
@ -18,7 +16,7 @@ impl Breadcrumb {
|
||||||
Self { path, symbols }
|
Self { path, symbols }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_separator<V: 'static>(&self, cx: &WindowContext) -> Div<V> {
|
fn render_separator<V: 'static>(&self, cx: &WindowContext) -> Node<V> {
|
||||||
div()
|
div()
|
||||||
.child(" › ")
|
.child(" › ")
|
||||||
.text_color(cx.theme().colors().text_muted)
|
.text_color(cx.theme().colors().text_muted)
|
||||||
|
@ -79,7 +77,7 @@ mod stories {
|
||||||
pub struct BreadcrumbStory;
|
pub struct BreadcrumbStory;
|
||||||
|
|
||||||
impl Render for BreadcrumbStory {
|
impl Render for BreadcrumbStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -235,12 +235,12 @@ mod stories {
|
||||||
empty_buffer_example, hello_world_rust_buffer_example,
|
empty_buffer_example, hello_world_rust_buffer_example,
|
||||||
hello_world_rust_buffer_with_status_example, Story,
|
hello_world_rust_buffer_with_status_example, Story,
|
||||||
};
|
};
|
||||||
use gpui::{rems, Div, Render};
|
use gpui::{rems, Node, Render};
|
||||||
|
|
||||||
pub struct BufferStory;
|
pub struct BufferStory;
|
||||||
|
|
||||||
impl Render for BufferStory {
|
impl Render for BufferStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{Div, Render, View, VisualContext};
|
use gpui::{Node, Render, View, VisualContext};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{h_stack, Icon, IconButton, IconColor, Input};
|
use crate::{h_stack, Icon, IconButton, IconColor, Input};
|
||||||
|
@ -27,9 +27,9 @@ impl BufferSearch {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for BufferSearch {
|
impl Render for BufferSearch {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Node<Self> {
|
||||||
h_stack()
|
h_stack()
|
||||||
.bg(cx.theme().colors().toolbar_background)
|
.bg(cx.theme().colors().toolbar_background)
|
||||||
.p_2()
|
.p_2()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
use crate::{prelude::*, Icon, IconButton, Input, Label, LabelColor};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
|
use gpui::prelude::*;
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::{Icon, IconButton, Input, Label, LabelColor};
|
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct ChatPanel {
|
pub struct ChatPanel {
|
||||||
|
@ -108,7 +107,7 @@ pub use stories::*;
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::{Panel, Story};
|
use crate::{Panel, Story};
|
||||||
|
|
||||||
|
@ -117,7 +116,7 @@ mod stories {
|
||||||
pub struct ChatPanelStory;
|
pub struct ChatPanelStory;
|
||||||
|
|
||||||
impl Render for ChatPanelStory {
|
impl Render for ChatPanelStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{prelude::*, Toggle};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon, List, ListHeader,
|
prelude::*, static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon,
|
||||||
|
List, ListHeader, Toggle,
|
||||||
};
|
};
|
||||||
|
use gpui::prelude::*;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct CollabPanel {
|
pub struct CollabPanel {
|
||||||
|
@ -92,12 +93,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct CollabPanelStory;
|
pub struct CollabPanelStory;
|
||||||
|
|
||||||
impl Render for CollabPanelStory {
|
impl Render for CollabPanelStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub use stories::*;
|
||||||
|
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ mod stories {
|
||||||
pub struct CommandPaletteStory;
|
pub struct CommandPaletteStory;
|
||||||
|
|
||||||
impl Render for CommandPaletteStory {
|
impl Render for CommandPaletteStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub use stories::*;
|
||||||
|
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ mod stories {
|
||||||
pub struct CopilotModalStory;
|
pub struct CopilotModalStory;
|
||||||
|
|
||||||
impl Render for CopilotModalStory {
|
impl Render for CopilotModalStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use gpui::{Div, Render, View, VisualContext};
|
use gpui::{Node, Render, View, VisualContext};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -48,9 +48,9 @@ impl EditorPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for EditorPane {
|
impl Render for EditorPane {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Node<Self> {
|
||||||
v_stack()
|
v_stack()
|
||||||
.w_full()
|
.w_full()
|
||||||
.h_full()
|
.h_full()
|
||||||
|
|
|
@ -40,12 +40,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct LanguageSelectorStory;
|
pub struct LanguageSelectorStory;
|
||||||
|
|
||||||
impl Render for LanguageSelectorStory {
|
impl Render for LanguageSelectorStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -40,12 +40,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{hello_world_rust_buffer_example, Story};
|
use crate::{hello_world_rust_buffer_example, Story};
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct MultiBufferStory;
|
pub struct MultiBufferStory;
|
||||||
|
|
||||||
impl Render for MultiBufferStory {
|
impl Render for MultiBufferStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use crate::utils::naive_format_distance_from_now;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
h_stack, prelude::*, static_new_notification_items_2, v_stack, Avatar, ButtonOrIconButton,
|
h_stack, prelude::*, static_new_notification_items_2, utils::naive_format_distance_from_now,
|
||||||
Icon, IconElement, Label, LabelColor, LineHeightStyle, ListHeaderMeta, ListSeparator,
|
v_stack, Avatar, ButtonOrIconButton, ClickHandler, Icon, IconElement, Label, LabelColor,
|
||||||
PublicPlayer, UnreadIndicator,
|
LineHeightStyle, ListHeader, ListHeaderMeta, ListSeparator, PublicPlayer, UnreadIndicator,
|
||||||
};
|
};
|
||||||
use crate::{ClickHandler, ListHeader};
|
use gpui::prelude::*;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct NotificationsPanel {
|
pub struct NotificationsPanel {
|
||||||
|
@ -353,12 +352,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{Panel, Story};
|
use crate::{Panel, Story};
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct NotificationsPanelStory;
|
pub struct NotificationsPanelStory;
|
||||||
|
|
||||||
impl Render for NotificationsPanelStory {
|
impl Render for NotificationsPanelStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl<V: 'static> Pane<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> ParentElement<V> for Pane<V> {
|
impl<V: 'static> ParentComponent<V> for Pane<V> {
|
||||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
&mut self.children
|
&mut self.children
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
static_project_panel_project_items, static_project_panel_single_items, Input, List, ListHeader,
|
prelude::*, static_project_panel_project_items, static_project_panel_single_items, Input, List,
|
||||||
|
ListHeader,
|
||||||
};
|
};
|
||||||
|
use gpui::prelude::*;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct ProjectPanel {
|
pub struct ProjectPanel {
|
||||||
|
@ -54,12 +55,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{Panel, Story};
|
use crate::{Panel, Story};
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct ProjectPanelStory;
|
pub struct ProjectPanelStory;
|
||||||
|
|
||||||
impl Render for ProjectPanelStory {
|
impl Render for ProjectPanelStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -36,12 +36,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct RecentProjectsStory;
|
pub struct RecentProjectsStory;
|
||||||
|
|
||||||
impl Render for RecentProjectsStory {
|
impl Render for RecentProjectsStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::prelude::*;
|
use crate::{prelude::*, Icon, IconButton, Tab};
|
||||||
use crate::{Icon, IconButton, Tab};
|
use gpui::prelude::*;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct TabBar {
|
pub struct TabBar {
|
||||||
|
@ -100,12 +100,12 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
pub struct TabBarStory;
|
pub struct TabBarStory;
|
||||||
|
|
||||||
impl Render for TabBarStory {
|
impl Render for TabBarStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -83,11 +83,11 @@ pub use stories::*;
|
||||||
mod stories {
|
mod stories {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
pub struct TerminalStory;
|
pub struct TerminalStory;
|
||||||
|
|
||||||
impl Render for TerminalStory {
|
impl Render for TerminalStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub use stories::*;
|
||||||
|
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ mod stories {
|
||||||
pub struct ThemeSelectorStory;
|
pub struct ThemeSelectorStory;
|
||||||
|
|
||||||
impl Render for ThemeSelectorStory {
|
impl Render for ThemeSelectorStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gpui::{Div, Render, View, VisualContext};
|
use gpui::{Node, Render, View, VisualContext};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::settings::user_settings;
|
use crate::settings::user_settings;
|
||||||
|
@ -86,9 +86,9 @@ impl TitleBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for TitleBar {
|
impl Render for TitleBar {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Node<Self> {
|
||||||
let settings = user_settings(cx);
|
let settings = user_settings(cx);
|
||||||
|
|
||||||
// let has_focus = cx.window_is_active();
|
// let has_focus = cx.window_is_active();
|
||||||
|
@ -202,9 +202,9 @@ mod stories {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for TitleBarStory {
|
impl Render for TitleBarStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Node<Self> {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
.child(Story::title_for::<_, TitleBar>(cx))
|
.child(Story::title_for::<_, TitleBar>(cx))
|
||||||
.child(Story::label(cx, "Default"))
|
.child(Story::label(cx, "Default"))
|
||||||
|
|
|
@ -73,7 +73,7 @@ mod stories {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol};
|
use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol};
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ mod stories {
|
||||||
pub struct ToolbarStory;
|
pub struct ToolbarStory;
|
||||||
|
|
||||||
impl Render for ToolbarStory {
|
impl Render for ToolbarStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -77,7 +77,7 @@ pub use stories::*;
|
||||||
|
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod stories {
|
mod stories {
|
||||||
use gpui::{Div, Render};
|
use gpui::{Node, Render};
|
||||||
|
|
||||||
use crate::Story;
|
use crate::Story;
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ mod stories {
|
||||||
pub struct TrafficLightsStory;
|
pub struct TrafficLightsStory;
|
||||||
|
|
||||||
impl Render for TrafficLightsStory {
|
impl Render for TrafficLightsStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
Story::container(cx)
|
Story::container(cx)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use gpui::{px, relative, Div, Render, Size, View, VisualContext};
|
use gpui::{px, relative, Node, Render, Size, View, VisualContext};
|
||||||
use settings2::Settings;
|
use settings2::Settings;
|
||||||
use theme2::ThemeSettings;
|
use theme2::ThemeSettings;
|
||||||
|
|
||||||
|
@ -192,9 +192,9 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for Workspace {
|
impl Render for Workspace {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Node<Self> {
|
||||||
let root_group = PaneGroup::new_panes(
|
let root_group = PaneGroup::new_panes(
|
||||||
vec![Pane::new(
|
vec![Pane::new(
|
||||||
"pane-0",
|
"pane-0",
|
||||||
|
@ -388,7 +388,7 @@ mod stories {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for WorkspaceStory {
|
impl Render for WorkspaceStory {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div().child(self.workspace.clone())
|
div().child(self.workspace.clone())
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{status_bar::StatusItemView, Axis, Workspace};
|
use crate::{status_bar::StatusItemView, Axis, Workspace};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, Action, AnyView, AppContext, Div, Entity, EntityId, EventEmitter, ParentElement, Render,
|
div, Action, AnyView, AppContext, Entity, EntityId, EventEmitter, Node, ParentComponent,
|
||||||
Subscription, View, ViewContext, WeakView, WindowContext,
|
Render, Subscription, View, ViewContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -419,7 +419,7 @@ impl Dock {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for Dock {
|
impl Render for Dock {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -621,7 +621,7 @@ impl PanelButtons {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
impl Render for PanelButtons {
|
impl Render for PanelButtons {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
// todo!()
|
// todo!()
|
||||||
|
@ -647,7 +647,7 @@ impl StatusItemView for PanelButtons {
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use gpui::{div, Div, ViewContext, WindowContext};
|
use gpui::{div, Node, ViewContext, WindowContext};
|
||||||
|
|
||||||
pub struct TestPanel {
|
pub struct TestPanel {
|
||||||
pub position: DockPosition,
|
pub position: DockPosition,
|
||||||
|
@ -672,7 +672,7 @@ pub mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for TestPanel {
|
impl Render for TestPanel {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div()
|
div()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, px, AnyView, Div, EventEmitter, FocusHandle, ParentElement, Render, StatelessInteractive,
|
div, prelude::*, px, AnyView, EventEmitter, FocusHandle, InteractiveComponent, Node,
|
||||||
Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
|
ParentComponent, Render, Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
|
||||||
};
|
};
|
||||||
use ui::v_stack;
|
use ui::v_stack;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ impl ModalLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for ModalLayer {
|
impl Render for ModalLayer {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let Some(active_modal) = &self.active_modal else {
|
let Some(active_modal) = &self.active_modal else {
|
||||||
|
|
|
@ -165,7 +165,7 @@ impl Workspace {
|
||||||
|
|
||||||
pub mod simple_message_notification {
|
pub mod simple_message_notification {
|
||||||
use super::{Notification, NotificationEvent};
|
use super::{Notification, NotificationEvent};
|
||||||
use gpui::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext};
|
use gpui::{AnyElement, AppContext, EventEmitter, Node, Render, TextStyle, ViewContext};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{borrow::Cow, sync::Arc};
|
use std::{borrow::Cow, sync::Arc};
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ pub mod simple_message_notification {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for MessageNotification {
|
impl Render for MessageNotification {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// mod dragged_item_receiver;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
item::{Item, ItemHandle, ItemSettings, WeakItemHandle},
|
item::{Item, ItemHandle, ItemSettings, WeakItemHandle},
|
||||||
toolbar::Toolbar,
|
toolbar::Toolbar,
|
||||||
|
@ -9,9 +7,9 @@ use crate::{
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::{HashMap, HashSet, VecDeque};
|
use collections::{HashMap, HashSet, VecDeque};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, register_action, AppContext, AsyncWindowContext, Component, Div, EntityId,
|
actions, prelude::*, register_action, AppContext, AsyncWindowContext, Component, EntityId,
|
||||||
EventEmitter, FocusHandle, Model, PromptLevel, Render, Task, View, ViewContext, VisualContext,
|
EventEmitter, FocusHandle, Model, Node, PromptLevel, Render, Task, View, ViewContext,
|
||||||
WeakView, WindowContext,
|
VisualContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use project2::{Project, ProjectEntryId, ProjectPath};
|
use project2::{Project, ProjectEntryId, ProjectPath};
|
||||||
|
@ -1903,7 +1901,7 @@ impl Pane {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
impl Render for Pane {
|
impl Render for Pane {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
v_stack()
|
v_stack()
|
||||||
|
@ -2928,7 +2926,7 @@ struct DraggedTab {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for DraggedTab {
|
impl Render for DraggedTab {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div().w_8().h_4().bg(gpui::red())
|
div().w_8().h_4().bg(gpui::red())
|
||||||
|
|
|
@ -2,8 +2,8 @@ use std::any::TypeId;
|
||||||
|
|
||||||
use crate::{ItemHandle, Pane};
|
use crate::{ItemHandle, Pane};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, AnyView, Component, Div, ParentElement, Render, Styled, Subscription, View, ViewContext,
|
div, AnyView, Component, Node, ParentComponent, Render, Styled, Subscription, View,
|
||||||
WindowContext,
|
ViewContext, WindowContext,
|
||||||
};
|
};
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
@ -34,7 +34,7 @@ pub struct StatusBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for StatusBar {
|
impl Render for StatusBar {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div()
|
div()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::ItemHandle;
|
use crate::ItemHandle;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyView, Div, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext,
|
AnyView, Entity, EntityId, EventEmitter, Node, Render, View, ViewContext, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum ToolbarItemEvent {
|
pub enum ToolbarItemEvent {
|
||||||
|
@ -52,7 +52,7 @@ pub struct Toolbar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for Toolbar {
|
impl Render for Toolbar {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
@ -36,12 +36,11 @@ use futures::{
|
||||||
Future, FutureExt, StreamExt,
|
Future, FutureExt, StreamExt,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, point, rems, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
|
actions, div, point, prelude::*, rems, size, Action, AnyModel, AnyView, AnyWeakView,
|
||||||
AsyncAppContext, AsyncWindowContext, Bounds, Component, Div, Entity, EntityId, EventEmitter,
|
AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Entity, EntityId,
|
||||||
FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, ParentElement, Point, Render, Size,
|
EventEmitter, FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, Node,
|
||||||
StatefulInteractive, StatelessInteractive, StatelessInteractivity, Styled, Subscription, Task,
|
ParentComponent, Point, Render, Size, Styled, Subscription, Task, View, ViewContext, WeakView,
|
||||||
View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle,
|
WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||||
WindowOptions,
|
|
||||||
};
|
};
|
||||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -443,7 +442,6 @@ struct Follower {
|
||||||
impl AppState {
|
impl AppState {
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn test(cx: &mut AppContext) -> Arc<Self> {
|
pub fn test(cx: &mut AppContext) -> Arc<Self> {
|
||||||
use gpui::Context;
|
|
||||||
use node_runtime::FakeNodeRuntime;
|
use node_runtime::FakeNodeRuntime;
|
||||||
use settings2::SettingsStore;
|
use settings2::SettingsStore;
|
||||||
|
|
||||||
|
@ -531,13 +529,7 @@ pub enum Event {
|
||||||
pub struct Workspace {
|
pub struct Workspace {
|
||||||
weak_self: WeakView<Self>,
|
weak_self: WeakView<Self>,
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
workspace_actions: Vec<
|
workspace_actions: Vec<Box<dyn Fn(Node<Workspace>) -> Node<Workspace>>>,
|
||||||
Box<
|
|
||||||
dyn Fn(
|
|
||||||
Div<Workspace, StatelessInteractivity<Workspace>>,
|
|
||||||
) -> Div<Workspace, StatelessInteractivity<Workspace>>,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
zoomed: Option<AnyWeakView>,
|
zoomed: Option<AnyWeakView>,
|
||||||
zoomed_position: Option<DockPosition>,
|
zoomed_position: Option<DockPosition>,
|
||||||
center: PaneGroup,
|
center: PaneGroup,
|
||||||
|
@ -3450,7 +3442,6 @@ impl Workspace {
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn test_new(project: Model<Project>, cx: &mut ViewContext<Self>) -> Self {
|
pub fn test_new(project: Model<Project>, cx: &mut ViewContext<Self>) -> Self {
|
||||||
use gpui::Context;
|
|
||||||
use node_runtime::FakeNodeRuntime;
|
use node_runtime::FakeNodeRuntime;
|
||||||
|
|
||||||
let client = project.read(cx).client();
|
let client = project.read(cx).client();
|
||||||
|
@ -3512,10 +3503,7 @@ impl Workspace {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_workspace_actions_listeners(
|
fn add_workspace_actions_listeners(&self, mut div: Node<Workspace>) -> Node<Workspace> {
|
||||||
&self,
|
|
||||||
mut div: Div<Workspace, StatelessInteractivity<Workspace>>,
|
|
||||||
) -> Div<Workspace, StatelessInteractivity<Workspace>> {
|
|
||||||
for action in self.workspace_actions.iter() {
|
for action in self.workspace_actions.iter() {
|
||||||
div = (action)(div)
|
div = (action)(div)
|
||||||
}
|
}
|
||||||
|
@ -3740,14 +3728,14 @@ fn notify_if_database_failed(workspace: WindowHandle<Workspace>, cx: &mut AsyncA
|
||||||
impl EventEmitter<Event> for Workspace {}
|
impl EventEmitter<Event> for Workspace {}
|
||||||
|
|
||||||
impl Render for Workspace {
|
impl Render for Workspace {
|
||||||
type Element = Div<Self>;
|
type Element = Node<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
let mut context = KeyContext::default();
|
let mut context = KeyContext::default();
|
||||||
context.add("Workspace");
|
context.add("Workspace");
|
||||||
|
|
||||||
self.add_workspace_actions_listeners(div())
|
self.add_workspace_actions_listeners(div())
|
||||||
.context(context)
|
.key_context(context)
|
||||||
.relative()
|
.relative()
|
||||||
.size_full()
|
.size_full()
|
||||||
.flex()
|
.flex()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue