Merge branch 'zed2-render' into zed2

This commit is contained in:
Max Brunsfeld 2023-10-30 15:37:00 -07:00
commit 58446c2715
51 changed files with 669 additions and 665 deletions

View File

@ -15,7 +15,7 @@ pub use test_context::*;
use crate::{
current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AppMetadata, AssetSource,
ClipboardItem, Context, DispatchPhase, DisplayId, Executor, FocusEvent, FocusHandle, FocusId,
KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly, Pixels, Platform, Point,
KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly, Pixels, Platform, Point, Render,
SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement,
TextSystem, View, Window, WindowContext, WindowHandle, WindowId,
};
@ -815,7 +815,7 @@ impl MainThread<AppContext> {
/// Opens a new window with the given option and the root view returned by the given function.
/// The function is invoked with a `WindowContext`, which can be used to interact with window-specific
/// functionality.
pub fn open_window<V: 'static>(
pub fn open_window<V: Render>(
&mut self,
options: crate::WindowOptions,
build_root_view: impl FnOnce(&mut WindowContext) -> View<V> + Send + 'static,
@ -898,10 +898,8 @@ impl<G: 'static> DerefMut for GlobalLease<G> {
/// Contains state associated with an active drag operation, started by dragging an element
/// within the window or by dragging into the app from the underlying platform.
pub(crate) struct AnyDrag {
pub drag_handle_view: Option<AnyView>,
pub view: AnyView,
pub cursor_offset: Point<Pixels>,
pub state: AnyBox,
pub state_type: TypeId,
}
#[cfg(test)]

View File

@ -147,7 +147,7 @@ pub struct Slot<T>(Model<T>);
pub struct AnyModel {
pub(crate) entity_id: EntityId,
entity_type: TypeId,
pub(crate) entity_type: TypeId,
entity_map: Weak<RwLock<EntityRefCounts>>,
}
@ -247,8 +247,8 @@ impl Eq for AnyModel {}
pub struct Model<T> {
#[deref]
#[deref_mut]
any_model: AnyModel,
entity_type: PhantomData<T>,
pub(crate) any_model: AnyModel,
pub(crate) entity_type: PhantomData<T>,
}
unsafe impl<T> Send for Model<T> {}
@ -272,6 +272,11 @@ impl<T: 'static> Model<T> {
}
}
/// Convert this into a dynamically typed model.
pub fn into_any(self) -> AnyModel {
self.any_model
}
pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
cx.entities.read(self)
}

View File

@ -4,7 +4,7 @@ pub(crate) use smallvec::SmallVec;
use std::{any::Any, mem};
pub trait Element<V: 'static> {
type ElementState: 'static;
type ElementState: 'static + Send;
fn id(&self) -> Option<ElementId>;

View File

@ -90,13 +90,11 @@ pub trait Context {
pub trait VisualContext: Context {
type ViewContext<'a, 'w, V>;
fn build_view<E, V>(
fn build_view<V>(
&mut self,
build_model: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
build_view_state: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
) -> Self::Result<View<V>>
where
E: Component<V>,
V: 'static + Send;
fn update_view<V: 'static, R>(
@ -171,27 +169,22 @@ impl<C: Context> Context for MainThread<C> {
impl<C: VisualContext> VisualContext for MainThread<C> {
type ViewContext<'a, 'w, V> = MainThread<C::ViewContext<'a, 'w, V>>;
fn build_view<E, V>(
fn build_view<V>(
&mut self,
build_model: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
build_view_state: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
) -> Self::Result<View<V>>
where
E: Component<V>,
V: 'static + Send,
{
self.0.build_view(
|cx| {
let cx = unsafe {
mem::transmute::<
&mut C::ViewContext<'_, '_, V>,
&mut MainThread<C::ViewContext<'_, '_, V>>,
>(cx)
};
build_model(cx)
},
render,
)
self.0.build_view(|cx| {
let cx = unsafe {
mem::transmute::<
&mut C::ViewContext<'_, '_, V>,
&mut MainThread<C::ViewContext<'_, '_, V>>,
>(cx)
};
build_view_state(cx)
})
}
fn update_view<V: 'static, R>(

View File

@ -1,7 +1,7 @@
use crate::{
point, px, Action, AnyBox, AnyDrag, AppContext, BorrowWindow, Bounds, Component,
DispatchContext, DispatchPhase, Element, ElementId, FocusHandle, KeyMatch, Keystroke,
Modifiers, Overflow, Pixels, Point, SharedString, Size, Style, StyleRefinement, View,
div, point, px, Action, AnyDrag, AnyView, AppContext, BorrowWindow, Bounds, Component,
DispatchContext, DispatchPhase, Div, Element, ElementId, FocusHandle, KeyMatch, Keystroke,
Modifiers, Overflow, Pixels, Point, Render, SharedString, Size, Style, StyleRefinement, View,
ViewContext,
};
use collections::HashMap;
@ -258,17 +258,17 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
self
}
fn on_drop<S: 'static>(
fn on_drop<W: 'static + Send>(
mut self,
listener: impl Fn(&mut V, S, &mut ViewContext<V>) + Send + 'static,
listener: impl Fn(&mut V, View<W>, &mut ViewContext<V>) + Send + 'static,
) -> Self
where
Self: Sized,
{
self.stateless_interaction().drop_listeners.push((
TypeId::of::<S>(),
Box::new(move |view, drag_state, cx| {
listener(view, *drag_state.downcast().unwrap(), cx);
TypeId::of::<W>(),
Box::new(move |view, dragged_view, cx| {
listener(view, dragged_view.downcast().unwrap(), cx);
}),
));
self
@ -314,36 +314,22 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
self
}
fn on_drag<S, R, E>(
fn on_drag<W>(
mut self,
listener: impl Fn(&mut V, &mut ViewContext<V>) -> Drag<S, R, V, E> + Send + 'static,
listener: impl Fn(&mut V, &mut ViewContext<V>) -> View<W> + Send + 'static,
) -> Self
where
Self: Sized,
S: Any + Send,
R: Fn(&mut V, &mut ViewContext<V>) -> E,
R: 'static + Send,
E: Component<V>,
W: 'static + Send + Render,
{
debug_assert!(
self.stateful_interaction().drag_listener.is_none(),
"calling on_drag more than once on the same element is not supported"
);
self.stateful_interaction().drag_listener =
Some(Box::new(move |view_state, cursor_offset, cx| {
let drag = listener(view_state, cx);
let drag_handle_view = Some(
View::for_handle(cx.model().upgrade().unwrap(), move |view_state, cx| {
(drag.render_drag_handle)(view_state, cx)
})
.into_any(),
);
AnyDrag {
drag_handle_view,
cursor_offset,
state: Box::new(drag.state),
state_type: TypeId::of::<S>(),
}
Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag {
view: listener(view_state, cx).into_any(),
cursor_offset,
}));
self
}
@ -412,7 +398,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
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.state_type
if *state_type == drag.view.entity_type()
&& group_bounds.contains_point(&mouse_position)
{
style.refine(&group_drag_style.style);
@ -421,7 +407,8 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
}
for (state_type, drag_over_style) in &self.as_stateless().drag_over_styles {
if *state_type == drag.state_type && bounds.contains_point(&mouse_position) {
if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position)
{
style.refine(drag_over_style);
}
}
@ -509,7 +496,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
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.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 {
@ -517,7 +504,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
.active_drag
.take()
.expect("checked for type drag state type above");
listener(view, drag.state, cx);
listener(view, drag.view.clone(), cx);
cx.notify();
cx.stop_propagation();
}
@ -685,7 +672,7 @@ impl<V> From<ElementId> for StatefulInteraction<V> {
}
}
type DropListener<V> = dyn Fn(&mut V, AnyBox, &mut ViewContext<V>) + 'static + Send;
type DropListener<V> = dyn Fn(&mut V, AnyView, &mut ViewContext<V>) + 'static + Send;
pub struct StatelessInteraction<V> {
pub dispatch_context: DispatchContext,
@ -866,7 +853,7 @@ pub struct Drag<S, R, V, E>
where
R: Fn(&mut V, &mut ViewContext<V>) -> E,
V: 'static,
E: Component<V>,
E: Component<()>,
{
pub state: S,
pub render_drag_handle: R,
@ -877,7 +864,7 @@ impl<S, R, V, E> Drag<S, R, V, E>
where
R: Fn(&mut V, &mut ViewContext<V>) -> E,
V: 'static,
E: Component<V>,
E: Component<()>,
{
pub fn new(state: S, render_drag_handle: R) -> Self {
Drag {
@ -888,6 +875,10 @@ 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)]
pub enum MouseButton {
Left,
@ -995,6 +986,14 @@ impl Deref for MouseExitEvent {
#[derive(Debug, Clone, Default)]
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
impl Render for ExternalPaths {
type Element = Div<Self>;
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
div() // Intentionally left empty because the platform will render icons for the dragged files
}
}
#[derive(Debug, Clone)]
pub enum FileDropEvent {
Entered {

View File

@ -1,50 +1,34 @@
use crate::{
AnyBox, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element, ElementId,
EntityId, LayoutId, Model, Pixels, Size, ViewContext, VisualContext, WeakModel, WindowContext,
AnyBox, AnyElement, AnyModel, AppContext, AvailableSpace, BorrowWindow, Bounds, Component,
Element, ElementId, EntityId, LayoutId, Model, Pixels, Size, ViewContext, VisualContext,
WeakModel, WindowContext,
};
use anyhow::{Context, Result};
use parking_lot::Mutex;
use std::{
marker::PhantomData,
sync::{Arc, Weak},
};
use std::{any::TypeId, marker::PhantomData, sync::Arc};
pub trait Render: 'static + Sized {
type Element: Element<Self> + 'static + Send;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element;
}
pub struct View<V> {
pub(crate) state: Model<V>,
render: Arc<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
pub(crate) model: Model<V>,
}
impl<V: 'static> View<V> {
pub fn for_handle<E>(
state: Model<V>,
render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
) -> View<V>
where
E: Component<V>,
{
View {
state,
render: Arc::new(Mutex::new(
move |state: &mut V, cx: &mut ViewContext<'_, '_, V>| render(state, cx).render(),
)),
}
}
}
impl<V: 'static> View<V> {
impl<V: Render> View<V> {
pub fn into_any(self) -> AnyView {
AnyView(Arc::new(self))
}
pub fn downgrade(&self) -> WeakView<V> {
WeakView {
state: self.state.downgrade(),
render: Arc::downgrade(&self.render),
}
}
}
impl<V: 'static> View<V> {
pub fn downgrade(&self) -> WeakView<V> {
WeakView {
model: self.model.downgrade(),
}
}
pub fn update<C, R>(
&self,
cx: &mut C,
@ -55,18 +39,21 @@ impl<V: 'static> View<V> {
{
cx.update_view(self, f)
}
pub fn read<'a>(&self, cx: &'a AppContext) -> &'a V {
self.model.read(cx)
}
}
impl<V> Clone for View<V> {
fn clone(&self) -> Self {
Self {
state: self.state.clone(),
render: self.render.clone(),
model: self.model.clone(),
}
}
}
impl<V: 'static, ParentViewState: 'static> Component<ParentViewState> for View<V> {
impl<V: Render, ParentViewState: 'static> Component<ParentViewState> for View<V> {
fn render(self) -> AnyElement<ParentViewState> {
AnyElement::new(EraseViewState {
view: self,
@ -75,11 +62,14 @@ impl<V: 'static, ParentViewState: 'static> Component<ParentViewState> for View<V
}
}
impl<V: 'static> Element<()> for View<V> {
impl<V> Element<()> for View<V>
where
V: Render,
{
type ElementState = AnyElement<V>;
fn id(&self) -> Option<crate::ElementId> {
Some(ElementId::View(self.state.entity_id))
Some(ElementId::View(self.model.entity_id))
}
fn initialize(
@ -89,7 +79,7 @@ impl<V: 'static> Element<()> for View<V> {
cx: &mut ViewContext<()>,
) -> Self::ElementState {
self.update(cx, |state, cx| {
let mut any_element = (self.render.lock())(state, cx);
let mut any_element = AnyElement::new(state.render(cx));
any_element.initialize(state, cx);
any_element
})
@ -116,15 +106,13 @@ impl<V: 'static> Element<()> for View<V> {
}
pub struct WeakView<V> {
pub(crate) state: WeakModel<V>,
render: Weak<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
pub(crate) model: WeakModel<V>,
}
impl<V: 'static> WeakView<V> {
pub fn upgrade(&self) -> Option<View<V>> {
let state = self.state.upgrade()?;
let render = self.render.upgrade()?;
Some(View { state, render })
let model = self.model.upgrade()?;
Some(View { model })
}
pub fn update<R>(
@ -140,8 +128,7 @@ impl<V: 'static> WeakView<V> {
impl<V> Clone for WeakView<V> {
fn clone(&self) -> Self {
Self {
state: self.state.clone(),
render: self.render.clone(),
model: self.model.clone(),
}
}
}
@ -153,13 +140,13 @@ struct EraseViewState<V, ParentV> {
unsafe impl<V, ParentV> Send for EraseViewState<V, ParentV> {}
impl<V: 'static, ParentV: 'static> Component<ParentV> for EraseViewState<V, ParentV> {
impl<V: Render, ParentV: 'static> Component<ParentV> for EraseViewState<V, ParentV> {
fn render(self) -> AnyElement<ParentV> {
AnyElement::new(self)
}
}
impl<V: 'static, ParentV: 'static> Element<ParentV> for EraseViewState<V, ParentV> {
impl<V: Render, ParentV: 'static> Element<ParentV> for EraseViewState<V, ParentV> {
type ElementState = AnyBox;
fn id(&self) -> Option<crate::ElementId> {
@ -196,23 +183,36 @@ impl<V: 'static, ParentV: 'static> Element<ParentV> for EraseViewState<V, Parent
}
trait ViewObject: Send + Sync {
fn entity_type(&self) -> TypeId;
fn entity_id(&self) -> EntityId;
fn model(&self) -> AnyModel;
fn initialize(&self, cx: &mut WindowContext) -> AnyBox;
fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
fn paint(&self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
}
impl<V: 'static> ViewObject for View<V> {
impl<V> ViewObject for View<V>
where
V: Render,
{
fn entity_type(&self) -> TypeId {
TypeId::of::<V>()
}
fn entity_id(&self) -> EntityId {
self.state.entity_id
self.model.entity_id
}
fn model(&self) -> AnyModel {
self.model.clone().into_any()
}
fn initialize(&self, cx: &mut WindowContext) -> AnyBox {
cx.with_element_id(self.entity_id(), |_global_id, cx| {
self.update(cx, |state, cx| {
let mut any_element = Box::new((self.render.lock())(state, cx));
let mut any_element = Box::new(AnyElement::new(state.render(cx)));
any_element.initialize(state, cx);
any_element as AnyBox
any_element
})
})
}
@ -240,6 +240,14 @@ impl<V: 'static> ViewObject for View<V> {
pub struct AnyView(Arc<dyn ViewObject>);
impl AnyView {
pub fn downcast<V: 'static + Send>(self) -> Option<View<V>> {
self.0.model().downcast().map(|model| View { model })
}
pub(crate) fn entity_type(&self) -> TypeId {
self.0.entity_type()
}
pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) {
let mut rendered_element = self.0.initialize(cx);
let layout_id = self.0.layout(&mut rendered_element, cx);
@ -309,6 +317,18 @@ impl<ParentV: 'static> Component<ParentV> for EraseAnyViewState<ParentV> {
}
}
impl<T, E> Render for T
where
T: 'static + FnMut(&mut WindowContext) -> E,
E: 'static + Send + Element<T>,
{
type Element = E;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
(self)(cx)
}
}
impl<ParentV: 'static> Element<ParentV> for EraseAnyViewState<ParentV> {
type ElementState = AnyBox;

View File

@ -1,11 +1,11 @@
use crate::{
px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, AsyncWindowContext, AvailableSpace,
Bounds, BoxShadow, Context, Corners, DevicePixels, DispatchContext, DisplayId, Edges, Effect,
EntityId, EventEmitter, ExternalPaths, FileDropEvent, FocusEvent, FontId, GlobalElementId,
GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke,
LayoutId, MainThread, MainThreadOnly, Model, ModelContext, Modifiers, MonochromeSprite,
MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas,
PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams,
EntityId, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla,
ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke, LayoutId,
MainThread, MainThreadOnly, Model, ModelContext, Modifiers, MonochromeSprite, MouseButton,
MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformWindow,
Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams,
RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, Subscription,
TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext, WeakModel, WeakView,
WindowOptions, SUBPIXEL_VARIANTS,
@ -891,15 +891,13 @@ impl<'a, 'w> WindowContext<'a, 'w> {
root_view.draw(available_space, cx);
});
if let Some(mut active_drag) = self.app.active_drag.take() {
if let Some(active_drag) = self.app.active_drag.take() {
self.stack(1, |cx| {
let offset = cx.mouse_position() - active_drag.cursor_offset;
cx.with_element_offset(Some(offset), |cx| {
let available_space =
size(AvailableSpace::MinContent, AvailableSpace::MinContent);
if let Some(drag_handle_view) = &mut active_drag.drag_handle_view {
drag_handle_view.draw(available_space, cx);
}
active_drag.view.draw(available_space, cx);
cx.active_drag = Some(active_drag);
});
});
@ -967,12 +965,12 @@ impl<'a, 'w> WindowContext<'a, 'w> {
InputEvent::FileDrop(file_drop) => match file_drop {
FileDropEvent::Entered { position, files } => {
self.window.mouse_position = position;
self.active_drag.get_or_insert_with(|| AnyDrag {
drag_handle_view: None,
cursor_offset: position,
state: Box::new(files),
state_type: TypeId::of::<ExternalPaths>(),
});
if self.active_drag.is_none() {
self.active_drag = Some(AnyDrag {
view: self.build_view(|_| files).into_any(),
cursor_offset: position,
});
}
InputEvent::MouseDown(MouseDownEvent {
position,
button: MouseButton::Left,
@ -1273,21 +1271,17 @@ impl Context for WindowContext<'_, '_> {
impl VisualContext for WindowContext<'_, '_> {
type ViewContext<'a, 'w, V> = ViewContext<'a, 'w, V>;
/// Builds a new view in the current window. The first argument is a function that builds
/// an entity representing the view's state. It is invoked with a `ViewContext` that provides
/// entity-specific access to the window and application state during construction. The second
/// argument is a render function that returns a component based on the view's state.
fn build_view<E, V>(
fn build_view<V>(
&mut self,
build_view_state: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
) -> Self::Result<View<V>>
where
E: crate::Component<V>,
V: 'static + Send,
{
let slot = self.app.entities.reserve();
let view = View::for_handle(slot.clone(), render);
let view = View {
model: slot.clone(),
};
let mut cx = ViewContext::mutable(&mut *self.app, &mut *self.window, view.downgrade());
let entity = build_view_state(&mut cx);
self.entities.insert(slot, entity);
@ -1300,7 +1294,7 @@ impl VisualContext for WindowContext<'_, '_> {
view: &View<T>,
update: impl FnOnce(&mut T, &mut Self::ViewContext<'_, '_, T>) -> R,
) -> Self::Result<R> {
let mut lease = self.app.entities.lease(&view.state);
let mut lease = self.app.entities.lease(&view.model);
let mut cx = ViewContext::mutable(&mut *self.app, &mut *self.window, view.downgrade());
let result = update(&mut *lease, &mut cx);
cx.app.entities.end_lease(lease);
@ -1556,7 +1550,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
}
pub fn model(&self) -> WeakModel<V> {
self.view.state.clone()
self.view.model.clone()
}
pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
@ -1635,7 +1629,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
) -> Subscription {
let window_handle = self.window.handle;
self.app.release_listeners.insert(
self.view.state.entity_id,
self.view.model.entity_id,
Box::new(move |this, cx| {
let this = this.downcast_mut().expect("invalid entity type");
// todo!("are we okay with silently swallowing the error?")
@ -1668,7 +1662,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
pub fn notify(&mut self) {
self.window_cx.notify();
self.window_cx.app.push_effect(Effect::Notify {
emitter: self.view.state.entity_id,
emitter: self.view.model.entity_id,
});
}
@ -1848,7 +1842,7 @@ where
V::Event: Any + Send,
{
pub fn emit(&mut self, event: V::Event) {
let emitter = self.view.state.entity_id;
let emitter = self.view.model.entity_id;
self.app.push_effect(Effect::Emit {
emitter,
event: Box::new(event),
@ -1882,16 +1876,11 @@ impl<'a, 'w, V> Context for ViewContext<'a, 'w, V> {
impl<V: 'static> VisualContext for ViewContext<'_, '_, V> {
type ViewContext<'a, 'w, V2> = ViewContext<'a, 'w, V2>;
fn build_view<E, V2>(
fn build_view<W: 'static + Send>(
&mut self,
build_view: impl FnOnce(&mut Self::ViewContext<'_, '_, V2>) -> V2,
render: impl Fn(&mut V2, &mut ViewContext<'_, '_, V2>) -> E + Send + 'static,
) -> Self::Result<View<V2>>
where
E: crate::Component<V2>,
V2: 'static + Send,
{
self.window_cx.build_view(build_view, render)
build_view: impl FnOnce(&mut Self::ViewContext<'_, '_, W>) -> W,
) -> Self::Result<View<W>> {
self.window_cx.build_view(build_view)
}
fn update_view<V2: 'static, R>(

View File

@ -1,13 +1,13 @@
use gpui2::px;
use crate::story::Story;
use gpui2::{px, Div, Render};
use ui::prelude::*;
use crate::story::Story;
#[derive(Component)]
pub struct ColorsStory;
impl ColorsStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ColorsStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let color_scales = theme2::default_color_scales();
Story::container(cx)

View File

@ -1,6 +1,6 @@
use gpui2::{
div, Focusable, KeyBinding, ParentElement, StatelessInteractive, Styled, View, VisualContext,
WindowContext,
div, Div, FocusEnabled, Focusable, KeyBinding, ParentElement, Render, StatefulInteraction,
StatelessInteractive, Styled, View, VisualContext, WindowContext,
};
use serde::Deserialize;
use theme2::theme;
@ -14,12 +14,10 @@ struct ActionB;
#[derive(Clone, Default, PartialEq, Deserialize)]
struct ActionC;
pub struct FocusStory {
text: View<()>,
}
pub struct FocusStory {}
impl FocusStory {
pub fn view(cx: &mut WindowContext) -> View<()> {
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.bind_keys([
KeyBinding::new("cmd-a", ActionA, Some("parent")),
KeyBinding::new("cmd-a", ActionB, Some("child-1")),
@ -27,8 +25,16 @@ impl FocusStory {
]);
cx.register_action_type::<ActionA>();
cx.register_action_type::<ActionB>();
let theme = theme(cx);
cx.build_view(move |cx| Self {})
}
}
impl Render for FocusStory {
type Element = Div<Self, StatefulInteraction<Self>, FocusEnabled<Self>>;
fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
let color_1 = theme.git_created;
let color_2 = theme.git_modified;
let color_3 = theme.git_deleted;
@ -38,80 +44,73 @@ impl FocusStory {
let child_1 = cx.focus_handle();
let child_2 = cx.focus_handle();
cx.build_view(
|_| (),
move |_, cx| {
div()
.id("parent")
.focusable()
.context("parent")
.on_action(|_, action: &ActionA, phase, cx| {
println!("Action A dispatched on parent during {:?}", phase);
})
.on_action(|_, action: &ActionB, phase, cx| {
println!("Action B dispatched on parent during {:?}", phase);
})
.on_focus(|_, _, _| println!("Parent focused"))
.on_blur(|_, _, _| println!("Parent blurred"))
.on_focus_in(|_, _, _| println!("Parent focus_in"))
.on_focus_out(|_, _, _| println!("Parent focus_out"))
.on_key_down(|_, event, phase, _| {
println!("Key down on parent {:?} {:?}", phase, event)
})
.on_key_up(|_, event, phase, _| println!("Key up on parent {:?} {:?}", phase, event))
.size_full()
.bg(color_1)
.focus(|style| style.bg(color_2))
.focus_in(|style| style.bg(color_3))
.child(
div()
.id("parent")
.focusable()
.context("parent")
.on_action(|_, action: &ActionA, phase, cx| {
println!("Action A dispatched on parent during {:?}", phase);
})
.track_focus(&child_1)
.context("child-1")
.on_action(|_, action: &ActionB, phase, cx| {
println!("Action B dispatched on parent during {:?}", phase);
println!("Action B dispatched on child 1 during {:?}", phase);
})
.on_focus(|_, _, _| println!("Parent focused"))
.on_blur(|_, _, _| println!("Parent blurred"))
.on_focus_in(|_, _, _| println!("Parent focus_in"))
.on_focus_out(|_, _, _| println!("Parent focus_out"))
.w_full()
.h_6()
.bg(color_4)
.focus(|style| style.bg(color_5))
.in_focus(|style| style.bg(color_6))
.on_focus(|_, _, _| println!("Child 1 focused"))
.on_blur(|_, _, _| println!("Child 1 blurred"))
.on_focus_in(|_, _, _| println!("Child 1 focus_in"))
.on_focus_out(|_, _, _| println!("Child 1 focus_out"))
.on_key_down(|_, event, phase, _| {
println!("Key down on parent {:?} {:?}", phase, event)
println!("Key down on child 1 {:?} {:?}", phase, event)
})
.on_key_up(|_, event, phase, _| {
println!("Key up on parent {:?} {:?}", phase, event)
println!("Key up on child 1 {:?} {:?}", phase, event)
})
.size_full()
.bg(color_1)
.focus(|style| style.bg(color_2))
.focus_in(|style| style.bg(color_3))
.child(
div()
.track_focus(&child_1)
.context("child-1")
.on_action(|_, action: &ActionB, phase, cx| {
println!("Action B dispatched on child 1 during {:?}", phase);
})
.w_full()
.h_6()
.bg(color_4)
.focus(|style| style.bg(color_5))
.in_focus(|style| style.bg(color_6))
.on_focus(|_, _, _| println!("Child 1 focused"))
.on_blur(|_, _, _| println!("Child 1 blurred"))
.on_focus_in(|_, _, _| println!("Child 1 focus_in"))
.on_focus_out(|_, _, _| println!("Child 1 focus_out"))
.on_key_down(|_, event, phase, _| {
println!("Key down on child 1 {:?} {:?}", phase, event)
})
.on_key_up(|_, event, phase, _| {
println!("Key up on child 1 {:?} {:?}", phase, event)
})
.child("Child 1"),
)
.child(
div()
.track_focus(&child_2)
.context("child-2")
.on_action(|_, action: &ActionC, phase, cx| {
println!("Action C dispatched on child 2 during {:?}", phase);
})
.w_full()
.h_6()
.bg(color_4)
.on_focus(|_, _, _| println!("Child 2 focused"))
.on_blur(|_, _, _| println!("Child 2 blurred"))
.on_focus_in(|_, _, _| println!("Child 2 focus_in"))
.on_focus_out(|_, _, _| println!("Child 2 focus_out"))
.on_key_down(|_, event, phase, _| {
println!("Key down on child 2 {:?} {:?}", phase, event)
})
.on_key_up(|_, event, phase, _| {
println!("Key up on child 2 {:?} {:?}", phase, event)
})
.child("Child 2"),
)
},
)
.child("Child 1"),
)
.child(
div()
.track_focus(&child_2)
.context("child-2")
.on_action(|_, action: &ActionC, phase, cx| {
println!("Action C dispatched on child 2 during {:?}", phase);
})
.w_full()
.h_6()
.bg(color_4)
.on_focus(|_, _, _| println!("Child 2 focused"))
.on_blur(|_, _, _| println!("Child 2 blurred"))
.on_focus_in(|_, _, _| println!("Child 2 focus_in"))
.on_focus_out(|_, _, _| println!("Child 2 focus_out"))
.on_key_down(|_, event, phase, _| {
println!("Key down on child 2 {:?} {:?}", phase, event)
})
.on_key_up(|_, event, phase, _| {
println!("Key up on child 2 {:?} {:?}", phase, event)
})
.child("Child 2"),
)
}
}

View File

@ -1,26 +1,23 @@
use gpui2::{AppContext, Context, View};
use crate::{
story::Story,
story_selector::{ComponentStory, ElementStory},
};
use gpui2::{Div, Render, StatefulInteraction, View, VisualContext};
use strum::IntoEnumIterator;
use ui::prelude::*;
use crate::story::Story;
use crate::story_selector::{ComponentStory, ElementStory};
pub struct KitchenSinkStory {}
pub struct KitchenSinkStory;
impl KitchenSinkStory {
pub fn new() -> Self {
Self {}
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|cx| Self)
}
}
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.build_model(|cx| Self::new());
let render = Self::render;
View::for_handle(state, render)
}
}
impl Render for KitchenSinkStory {
type Element = Div<Self, StatefulInteraction<Self>>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let element_stories = ElementStory::iter()
.map(|selector| selector.story(cx))
.collect::<Vec<_>>();

View File

@ -1,54 +1,54 @@
use gpui2::{
div, px, Component, ParentElement, SharedString, Styled, View, VisualContext, WindowContext,
div, px, Component, Div, ParentElement, Render, SharedString, StatefulInteraction, Styled,
View, VisualContext, WindowContext,
};
use theme2::theme;
pub struct ScrollStory {
text: View<()>,
}
pub struct ScrollStory;
impl ScrollStory {
pub fn view(cx: &mut WindowContext) -> View<()> {
cx.build_view(|cx| (), move |_, cx| checkerboard(cx, 1))
pub fn view(cx: &mut WindowContext) -> View<ScrollStory> {
cx.build_view(|cx| ScrollStory)
}
}
fn checkerboard<S>(cx: &mut WindowContext, depth: usize) -> impl Component<S>
where
S: 'static + Send + Sync,
{
let theme = theme(cx);
let color_1 = theme.git_created;
let color_2 = theme.git_modified;
impl Render for ScrollStory {
type Element = Div<Self, StatefulInteraction<Self>>;
div()
.id("parent")
.bg(theme.background)
.size_full()
.overflow_scroll()
.children((0..10).map(|row| {
div()
.w(px(1000.))
.h(px(100.))
.flex()
.flex_row()
.children((0..10).map(|column| {
let id = SharedString::from(format!("{}, {}", row, column));
let bg = if row % 2 == column % 2 {
color_1
} else {
color_2
};
div().id(id).bg(bg).size(px(100. / depth as f32)).when(
row >= 5 && column >= 5,
|d| {
d.overflow_scroll()
.child(div().size(px(50.)).bg(color_1))
.child(div().size(px(50.)).bg(color_2))
.child(div().size(px(50.)).bg(color_1))
.child(div().size(px(50.)).bg(color_2))
},
)
}))
}))
fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
let color_1 = theme.git_created;
let color_2 = theme.git_modified;
div()
.id("parent")
.bg(theme.background)
.size_full()
.overflow_scroll()
.children((0..10).map(|row| {
div()
.w(px(1000.))
.h(px(100.))
.flex()
.flex_row()
.children((0..10).map(|column| {
let id = SharedString::from(format!("{}, {}", row, column));
let bg = if row % 2 == column % 2 {
color_1
} else {
color_2
};
div().id(id).bg(bg).size(px(100. as f32)).when(
row >= 5 && column >= 5,
|d| {
d.overflow_scroll()
.child(div().size(px(50.)).bg(color_1))
.child(div().size(px(50.)).bg(color_2))
.child(div().size(px(50.)).bg(color_1))
.child(div().size(px(50.)).bg(color_2))
},
)
}))
}))
}
}

View File

@ -1,20 +1,21 @@
use gpui2::{div, white, ParentElement, Styled, View, VisualContext, WindowContext};
use gpui2::{div, white, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext};
pub struct TextStory {
text: View<()>,
}
pub struct TextStory;
impl TextStory {
pub fn view(cx: &mut WindowContext) -> View<()> {
cx.build_view(|cx| (), |_, cx| {
div()
.size_full()
.bg(white())
.child(concat!(
"The quick brown fox jumps over the lazy dog. ",
"Meanwhile, the lazy dog decided it was time for a change. ",
"He started daily workout routines, ate healthier and became the fastest dog in town.",
))
})
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|cx| Self)
}
}
impl Render for TextStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> Self::Element {
div().size_full().bg(white()).child(concat!(
"The quick brown fox jumps over the lazy dog. ",
"Meanwhile, the lazy dog decided it was time for a change. ",
"He started daily workout routines, ate healthier and became the fastest dog in town.",
))
}
}

View File

@ -1,15 +1,16 @@
use gpui2::{px, rgb, Div, Hsla};
use gpui2::{px, rgb, Div, Hsla, Render};
use ui::prelude::*;
use crate::story::Story;
/// A reimplementation of the MDN `z-index` example, found here:
/// [https://developer.mozilla.org/en-US/docs/Web/CSS/z-index](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index).
#[derive(Component)]
pub struct ZIndexStory;
impl ZIndexStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ZIndexStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title(cx, "z-index"))
.child(

View File

@ -7,7 +7,7 @@ use clap::builder::PossibleValue;
use clap::ValueEnum;
use gpui2::{AnyView, VisualContext};
use strum::{EnumIter, EnumString, IntoEnumIterator};
use ui::prelude::*;
use ui::{prelude::*, AvatarStory, ButtonStory, DetailsStory, IconStory, InputStory, LabelStory};
#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)]
#[strum(serialize_all = "snake_case")]
@ -28,19 +28,17 @@ pub enum ElementStory {
impl ElementStory {
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
match self {
Self::Avatar => { cx.build_view(|cx| (), |_, _| ui::AvatarStory.render()) }.into_any(),
Self::Button => { cx.build_view(|cx| (), |_, _| ui::ButtonStory.render()) }.into_any(),
Self::Colors => { cx.build_view(|cx| (), |_, _| ColorsStory.render()) }.into_any(),
Self::Details => {
{ cx.build_view(|cx| (), |_, _| ui::DetailsStory.render()) }.into_any()
}
Self::Colors => cx.build_view(|_| ColorsStory).into_any(),
Self::Avatar => cx.build_view(|_| AvatarStory).into_any(),
Self::Button => cx.build_view(|_| ButtonStory).into_any(),
Self::Details => cx.build_view(|_| DetailsStory).into_any(),
Self::Focus => FocusStory::view(cx).into_any(),
Self::Icon => { cx.build_view(|cx| (), |_, _| ui::IconStory.render()) }.into_any(),
Self::Input => { cx.build_view(|cx| (), |_, _| ui::InputStory.render()) }.into_any(),
Self::Label => { cx.build_view(|cx| (), |_, _| ui::LabelStory.render()) }.into_any(),
Self::Icon => cx.build_view(|_| IconStory).into_any(),
Self::Input => cx.build_view(|_| InputStory).into_any(),
Self::Label => cx.build_view(|_| LabelStory).into_any(),
Self::Scroll => ScrollStory::view(cx).into_any(),
Self::Text => TextStory::view(cx).into_any(),
Self::ZIndex => { cx.build_view(|cx| (), |_, _| ZIndexStory.render()) }.into_any(),
Self::ZIndex => cx.build_view(|_| ZIndexStory).into_any(),
}
}
}
@ -79,69 +77,31 @@ pub enum ComponentStory {
impl ComponentStory {
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
match self {
Self::AssistantPanel => {
{ cx.build_view(|cx| (), |_, _| ui::AssistantPanelStory.render()) }.into_any()
}
Self::Buffer => { cx.build_view(|cx| (), |_, _| ui::BufferStory.render()) }.into_any(),
Self::Breadcrumb => {
{ cx.build_view(|cx| (), |_, _| ui::BreadcrumbStory.render()) }.into_any()
}
Self::ChatPanel => {
{ cx.build_view(|cx| (), |_, _| ui::ChatPanelStory.render()) }.into_any()
}
Self::CollabPanel => {
{ cx.build_view(|cx| (), |_, _| ui::CollabPanelStory.render()) }.into_any()
}
Self::CommandPalette => {
{ cx.build_view(|cx| (), |_, _| ui::CommandPaletteStory.render()) }.into_any()
}
Self::ContextMenu => {
{ cx.build_view(|cx| (), |_, _| ui::ContextMenuStory.render()) }.into_any()
}
Self::Facepile => {
{ cx.build_view(|cx| (), |_, _| ui::FacepileStory.render()) }.into_any()
}
Self::Keybinding => {
{ cx.build_view(|cx| (), |_, _| ui::KeybindingStory.render()) }.into_any()
}
Self::LanguageSelector => {
{ cx.build_view(|cx| (), |_, _| ui::LanguageSelectorStory.render()) }.into_any()
}
Self::MultiBuffer => {
{ cx.build_view(|cx| (), |_, _| ui::MultiBufferStory.render()) }.into_any()
}
Self::NotificationsPanel => {
{ cx.build_view(|cx| (), |_, _| ui::NotificationsPanelStory.render()) }.into_any()
}
Self::Palette => {
{ cx.build_view(|cx| (), |_, _| ui::PaletteStory.render()) }.into_any()
}
Self::Panel => { cx.build_view(|cx| (), |_, _| ui::PanelStory.render()) }.into_any(),
Self::ProjectPanel => {
{ cx.build_view(|cx| (), |_, _| ui::ProjectPanelStory.render()) }.into_any()
}
Self::RecentProjects => {
{ cx.build_view(|cx| (), |_, _| ui::RecentProjectsStory.render()) }.into_any()
}
Self::Tab => { cx.build_view(|cx| (), |_, _| ui::TabStory.render()) }.into_any(),
Self::TabBar => { cx.build_view(|cx| (), |_, _| ui::TabBarStory.render()) }.into_any(),
Self::Terminal => {
{ cx.build_view(|cx| (), |_, _| ui::TerminalStory.render()) }.into_any()
}
Self::ThemeSelector => {
{ cx.build_view(|cx| (), |_, _| ui::ThemeSelectorStory.render()) }.into_any()
}
Self::AssistantPanel => cx.build_view(|_| ui::AssistantPanelStory).into_any(),
Self::Buffer => cx.build_view(|_| ui::BufferStory).into_any(),
Self::Breadcrumb => cx.build_view(|_| ui::BreadcrumbStory).into_any(),
Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into_any(),
Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into_any(),
Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into_any(),
Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into_any(),
Self::Facepile => cx.build_view(|_| ui::FacepileStory).into_any(),
Self::Keybinding => cx.build_view(|_| ui::KeybindingStory).into_any(),
Self::LanguageSelector => cx.build_view(|_| ui::LanguageSelectorStory).into_any(),
Self::MultiBuffer => cx.build_view(|_| ui::MultiBufferStory).into_any(),
Self::NotificationsPanel => cx.build_view(|cx| ui::NotificationsPanelStory).into_any(),
Self::Palette => cx.build_view(|cx| ui::PaletteStory).into_any(),
Self::Panel => cx.build_view(|cx| ui::PanelStory).into_any(),
Self::ProjectPanel => cx.build_view(|_| ui::ProjectPanelStory).into_any(),
Self::RecentProjects => cx.build_view(|_| ui::RecentProjectsStory).into_any(),
Self::Tab => cx.build_view(|_| ui::TabStory).into_any(),
Self::TabBar => cx.build_view(|_| ui::TabBarStory).into_any(),
Self::Terminal => cx.build_view(|_| ui::TerminalStory).into_any(),
Self::ThemeSelector => cx.build_view(|_| ui::ThemeSelectorStory).into_any(),
Self::Toast => cx.build_view(|_| ui::ToastStory).into_any(),
Self::Toolbar => cx.build_view(|_| ui::ToolbarStory).into_any(),
Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into_any(),
Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into_any(),
Self::TitleBar => ui::TitleBarStory::view(cx).into_any(),
Self::Toast => { cx.build_view(|cx| (), |_, _| ui::ToastStory.render()) }.into_any(),
Self::Toolbar => {
{ cx.build_view(|cx| (), |_, _| ui::ToolbarStory.render()) }.into_any()
}
Self::TrafficLights => {
{ cx.build_view(|cx| (), |_, _| ui::TrafficLightsStory.render()) }.into_any()
}
Self::Copilot => {
{ cx.build_view(|cx| (), |_, _| ui::CopilotModalStory.render()) }.into_any()
}
Self::Workspace => ui::WorkspaceStory::view(cx).into_any(),
}
}

View File

@ -9,8 +9,8 @@ use std::sync::Arc;
use clap::Parser;
use gpui2::{
div, px, size, AnyView, AppContext, Bounds, ViewContext, VisualContext, WindowBounds,
WindowOptions,
div, px, size, AnyView, AppContext, Bounds, Div, Render, ViewContext, VisualContext,
WindowBounds, WindowOptions,
};
use log::LevelFilter;
use settings2::{default_settings, Settings, SettingsStore};
@ -82,12 +82,7 @@ fn main() {
}),
..Default::default()
},
move |cx| {
cx.build_view(
|cx| StoryWrapper::new(selector.story(cx)),
StoryWrapper::render,
)
},
move |cx| cx.build_view(|cx| StoryWrapper::new(selector.story(cx))),
);
cx.activate(true);
@ -103,8 +98,12 @@ impl StoryWrapper {
pub(crate) fn new(story: AnyView) -> Self {
Self { story }
}
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
impl Render for StoryWrapper {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div()
.flex()
.flex_col()

View File

@ -1,7 +1,6 @@
use gpui2::{rems, AbsoluteLength};
use crate::prelude::*;
use crate::{Icon, IconButton, Label, Panel, PanelSide};
use gpui2::{rems, AbsoluteLength};
#[derive(Component)]
pub struct AssistantPanel {
@ -76,15 +75,15 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
#[derive(Component)]
use crate::Story;
use gpui2::{Div, Render};
pub struct AssistantPanelStory;
impl AssistantPanelStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for AssistantPanelStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, AssistantPanel>(cx))
.child(Story::label(cx, "Default"))

View File

@ -73,21 +73,17 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use super::*;
use crate::Story;
use gpui2::Render;
use std::str::FromStr;
use crate::Story;
use super::*;
#[derive(Component)]
pub struct BreadcrumbStory;
impl BreadcrumbStory {
fn render<V: 'static>(
self,
view_state: &mut V,
cx: &mut ViewContext<V>,
) -> impl Component<V> {
impl Render for BreadcrumbStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)

View File

@ -233,20 +233,19 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::rems;
use super::*;
use crate::{
empty_buffer_example, hello_world_rust_buffer_example,
hello_world_rust_buffer_with_status_example, Story,
};
use gpui2::{rems, Div, Render};
use super::*;
#[derive(Component)]
pub struct BufferStory;
impl BufferStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for BufferStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)

View File

@ -1,4 +1,4 @@
use gpui2::{AppContext, Context, View};
use gpui2::{Div, Render, View, VisualContext};
use crate::prelude::*;
use crate::{h_stack, Icon, IconButton, IconColor, Input};
@ -21,15 +21,15 @@ impl BufferSearch {
cx.notify();
}
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.build_model(|cx| Self::new());
let render = Self::render;
View::for_handle(state, render)
}
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|cx| Self::new())
}
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
impl Render for BufferSearch {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
let theme = theme(cx);
h_stack().bg(theme.toolbar).p_2().child(

View File

@ -108,16 +108,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use chrono::DateTime;
use gpui2::{Div, Render};
use crate::{Panel, Story};
use super::*;
#[derive(Component)]
pub struct ChatPanelStory;
impl ChatPanelStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ChatPanelStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ChatPanel>(cx))
.child(Story::label(cx, "Default"))

View File

@ -89,15 +89,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct CollabPanelStory;
impl CollabPanelStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for CollabPanelStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, CollabPanel>(cx))
.child(Story::label(cx, "Default"))

View File

@ -27,15 +27,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::{Div, Render};
use crate::Story;
use super::*;
#[derive(Component)]
pub struct CommandPaletteStory;
impl CommandPaletteStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for CommandPaletteStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, CommandPalette>(cx))
.child(Story::label(cx, "Default"))

View File

@ -68,15 +68,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::story::Story;
use super::*;
use crate::story::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct ContextMenuStory;
impl ContextMenuStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ContextMenuStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ContextMenu>(cx))
.child(Story::label(cx, "Default"))

View File

@ -25,15 +25,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::{Div, Render};
use crate::Story;
use super::*;
#[derive(Component)]
pub struct CopilotModalStory;
impl CopilotModalStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for CopilotModalStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, CopilotModal>(cx))
.child(Story::label(cx, "Default"))

View File

@ -1,6 +1,6 @@
use std::path::PathBuf;
use gpui2::{AppContext, Context, View};
use gpui2::{Div, Render, View, VisualContext};
use crate::prelude::*;
use crate::{
@ -20,7 +20,7 @@ pub struct EditorPane {
impl EditorPane {
pub fn new(
cx: &mut AppContext,
cx: &mut ViewContext<Self>,
tabs: Vec<Tab>,
path: PathBuf,
symbols: Vec<Symbol>,
@ -42,15 +42,15 @@ impl EditorPane {
cx.notify();
}
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.build_model(|cx| hello_world_rust_editor_with_status_example(cx));
let render = Self::render;
View::for_handle(state, render)
}
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|cx| hello_world_rust_editor_with_status_example(cx))
}
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
impl Render for EditorPane {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
v_stack()
.w_full()
.h_full()

View File

@ -31,15 +31,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::{static_players, Story};
use super::*;
use crate::{static_players, Story};
use gpui2::{Div, Render};
#[derive(Component)]
pub struct FacepileStory;
impl FacepileStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for FacepileStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let players = static_players();
Story::container(cx)

View File

@ -158,17 +158,17 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use super::*;
use crate::Story;
use gpui2::{Div, Render};
use itertools::Itertools;
use crate::Story;
use super::*;
#[derive(Component)]
pub struct KeybindingStory;
impl KeybindingStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for KeybindingStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let all_modifier_permutations = ModifierKey::iter().permutations(2);
Story::container(cx)

View File

@ -38,15 +38,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct LanguageSelectorStory;
impl LanguageSelectorStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for LanguageSelectorStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, LanguageSelector>(cx))
.child(Story::label(cx, "Default"))

View File

@ -40,15 +40,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::{hello_world_rust_buffer_example, Story};
use super::*;
use crate::{hello_world_rust_buffer_example, Story};
use gpui2::{Div, Render};
#[derive(Component)]
pub struct MultiBufferStory;
impl MultiBufferStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for MultiBufferStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)

View File

@ -48,15 +48,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::{Panel, Story};
use super::*;
use crate::{Panel, Story};
use gpui2::{Div, Render};
#[derive(Component)]
pub struct NotificationsPanelStory;
impl NotificationsPanelStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for NotificationsPanelStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, NotificationsPanel>(cx))
.child(Story::label(cx, "Default"))

View File

@ -152,58 +152,71 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::{Div, Render};
use crate::{ModifierKeys, Story};
use super::*;
#[derive(Component)]
pub struct PaletteStory;
impl PaletteStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
Story::container(cx)
.child(Story::title_for::<_, Palette>(cx))
.child(Story::label(cx, "Default"))
.child(Palette::new("palette-1"))
.child(Story::label(cx, "With Items"))
.child(
Palette::new("palette-2")
.placeholder("Execute a command...")
.items(vec![
PaletteItem::new("theme selector: toggle").keybinding(
Keybinding::new_chord(
("k".to_string(), ModifierKeys::new().command(true)),
("t".to_string(), ModifierKeys::new().command(true)),
impl Render for PaletteStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
{
Story::container(cx)
.child(Story::title_for::<_, Palette>(cx))
.child(Story::label(cx, "Default"))
.child(Palette::new("palette-1"))
.child(Story::label(cx, "With Items"))
.child(
Palette::new("palette-2")
.placeholder("Execute a command...")
.items(vec![
PaletteItem::new("theme selector: toggle").keybinding(
Keybinding::new_chord(
("k".to_string(), ModifierKeys::new().command(true)),
("t".to_string(), ModifierKeys::new().command(true)),
),
),
),
PaletteItem::new("assistant: inline assist").keybinding(
Keybinding::new(
"enter".to_string(),
ModifierKeys::new().command(true),
PaletteItem::new("assistant: inline assist").keybinding(
Keybinding::new(
"enter".to_string(),
ModifierKeys::new().command(true),
),
),
),
PaletteItem::new("assistant: quote selection").keybinding(
Keybinding::new(">".to_string(), ModifierKeys::new().command(true)),
),
PaletteItem::new("assistant: toggle focus").keybinding(
Keybinding::new("?".to_string(), ModifierKeys::new().command(true)),
),
PaletteItem::new("auto update: check"),
PaletteItem::new("auto update: view release notes"),
PaletteItem::new("branches: open recent").keybinding(Keybinding::new(
"b".to_string(),
ModifierKeys::new().command(true).alt(true),
)),
PaletteItem::new("chat panel: toggle focus"),
PaletteItem::new("cli: install"),
PaletteItem::new("client: sign in"),
PaletteItem::new("client: sign out"),
PaletteItem::new("editor: cancel").keybinding(Keybinding::new(
"escape".to_string(),
ModifierKeys::new(),
)),
]),
)
PaletteItem::new("assistant: quote selection").keybinding(
Keybinding::new(
">".to_string(),
ModifierKeys::new().command(true),
),
),
PaletteItem::new("assistant: toggle focus").keybinding(
Keybinding::new(
"?".to_string(),
ModifierKeys::new().command(true),
),
),
PaletteItem::new("auto update: check"),
PaletteItem::new("auto update: view release notes"),
PaletteItem::new("branches: open recent").keybinding(
Keybinding::new(
"b".to_string(),
ModifierKeys::new().command(true).alt(true),
),
),
PaletteItem::new("chat panel: toggle focus"),
PaletteItem::new("cli: install"),
PaletteItem::new("client: sign in"),
PaletteItem::new("client: sign out"),
PaletteItem::new("editor: cancel").keybinding(Keybinding::new(
"escape".to_string(),
ModifierKeys::new(),
)),
]),
)
}
}
}
}

View File

@ -128,17 +128,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::{Label, Story};
use super::*;
use crate::{Label, Story};
use gpui2::{Div, Render};
#[derive(Component)]
pub struct PanelStory;
impl PanelStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for PanelStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Panel<V>>(cx))
.child(Story::title_for::<_, Panel<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(
Panel::new("panel", cx).child(

View File

@ -1,4 +1,4 @@
use gpui2::{hsla, red, AnyElement, ElementId, ExternalPaths, Hsla, Length, Size};
use gpui2::{hsla, red, AnyElement, ElementId, ExternalPaths, Hsla, Length, Size, View};
use smallvec::SmallVec;
use crate::prelude::*;
@ -18,13 +18,6 @@ pub struct Pane<V: 'static> {
children: SmallVec<[AnyElement<V>; 2]>,
}
// impl<V: 'static> IntoAnyElement<V> for Pane<V> {
// fn into_any(self) -> AnyElement<V> {
// (move |view_state: &mut V, cx: &mut ViewContext<'_, '_, V>| self.render(view_state, cx))
// .into_any()
// }
// }
impl<V: 'static> Pane<V> {
pub fn new(id: impl Into<ElementId>, size: Size<Length>) -> Self {
// Fill is only here for debugging purposes, remove before release
@ -57,8 +50,8 @@ impl<V: 'static> Pane<V> {
.z_index(1)
.id("drag-target")
.drag_over::<ExternalPaths>(|d| d.bg(red()))
.on_drop(|_, files: ExternalPaths, _| {
dbg!("dropped files!", files);
.on_drop(|_, files: View<ExternalPaths>, cx| {
dbg!("dropped files!", files.read(cx));
})
.absolute()
.inset_0(),

View File

@ -57,15 +57,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::{Panel, Story};
use super::*;
use crate::{Panel, Story};
use gpui2::{Div, Render};
#[derive(Component)]
pub struct ProjectPanelStory;
impl ProjectPanelStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ProjectPanelStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ProjectPanel>(cx))
.child(Story::label(cx, "Default"))

View File

@ -34,15 +34,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct RecentProjectsStory;
impl RecentProjectsStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for RecentProjectsStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, RecentProjects>(cx))
.child(Story::label(cx, "Default"))

View File

@ -1,5 +1,6 @@
use crate::prelude::*;
use crate::{Icon, IconColor, IconElement, Label, LabelColor};
use gpui2::{black, red, Div, ElementId, Render, View, VisualContext};
#[derive(Component, Clone)]
pub struct Tab {
@ -19,6 +20,14 @@ struct TabDragState {
title: String,
}
impl Render for TabDragState {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div().w_8().h_4().bg(red())
}
}
impl Tab {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
@ -118,12 +127,10 @@ impl Tab {
div()
.id(self.id.clone())
.on_drag(move |_view, _cx| {
Drag::new(drag_state.clone(), |view, cx| div().w_8().h_4().bg(red()))
})
.on_drag(move |_view, cx| cx.build_view(|cx| drag_state.clone()))
.drag_over::<TabDragState>(|d| d.bg(black()))
.on_drop(|_view, state: TabDragState, cx| {
dbg!(state);
.on_drop(|_view, state: View<TabDragState>, cx| {
dbg!(state.read(cx));
})
.px_2()
.py_0p5()
@ -160,23 +167,21 @@ impl Tab {
}
}
use gpui2::{black, red, Drag, ElementId};
#[cfg(feature = "stories")]
pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use super::*;
use crate::{h_stack, v_stack, Icon, Story};
use strum::IntoEnumIterator;
use crate::{h_stack, v_stack, Icon, Story};
use super::*;
#[derive(Component)]
pub struct TabStory;
impl TabStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for TabStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let git_statuses = GitStatus::iter();
let fs_statuses = FileSystemStatus::iter();

View File

@ -92,15 +92,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct TabBarStory;
impl TabBarStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for TabBarStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, TabBar>(cx))
.child(Story::label(cx, "Default"))

View File

@ -83,15 +83,15 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
#[derive(Component)]
use crate::Story;
use gpui2::{Div, Render};
pub struct TerminalStory;
impl TerminalStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for TerminalStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Terminal>(cx))
.child(Story::label(cx, "Default"))

View File

@ -39,15 +39,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::{Div, Render};
use crate::Story;
use super::*;
#[derive(Component)]
pub struct ThemeSelectorStory;
impl ThemeSelectorStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ThemeSelectorStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ThemeSelector>(cx))
.child(Story::label(cx, "Default"))

View File

@ -1,7 +1,7 @@
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use gpui2::{AppContext, Context, ModelContext, View};
use gpui2::{Div, Render, View, VisualContext};
use crate::prelude::*;
use crate::settings::user_settings;
@ -28,7 +28,7 @@ pub struct TitleBar {
}
impl TitleBar {
pub fn new(cx: &mut ModelContext<Self>) -> Self {
pub fn new(cx: &mut ViewContext<Self>) -> Self {
let is_active = Arc::new(AtomicBool::new(true));
let active = is_active.clone();
@ -80,15 +80,15 @@ impl TitleBar {
cx.notify();
}
pub fn view(cx: &mut AppContext, livestream: Option<Livestream>) -> View<Self> {
{
let state = cx.build_model(|cx| Self::new(cx).set_livestream(livestream));
let render = Self::render;
View::for_handle(state, render)
}
pub fn view(cx: &mut WindowContext, livestream: Option<Livestream>) -> View<Self> {
cx.build_view(|cx| Self::new(cx).set_livestream(livestream))
}
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
impl Render for TitleBar {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
let theme = theme(cx);
let settings = user_settings(cx);
@ -187,26 +187,25 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
pub struct TitleBarStory {
title_bar: View<TitleBar>,
}
impl TitleBarStory {
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.build_model(|cx| Self {
title_bar: TitleBar::view(cx, None),
});
let render = Self::render;
View::for_handle(state, render)
}
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|cx| Self {
title_bar: TitleBar::view(cx, None),
})
}
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
impl Render for TitleBarStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
Story::container(cx)
.child(Story::title_for::<_, TitleBar>(cx))
.child(Story::label(cx, "Default"))

View File

@ -72,17 +72,20 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::{Div, Render};
use crate::{Label, Story};
use super::*;
#[derive(Component)]
pub struct ToastStory;
impl ToastStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ToastStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Toast<V>>(cx))
.child(Story::title_for::<_, Toast<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(Toast::new(ToastOrigin::Bottom).child(Label::new("label")))
}

View File

@ -75,19 +75,22 @@ mod stories {
use std::path::PathBuf;
use std::str::FromStr;
use gpui2::{Div, Render};
use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol};
use super::*;
#[derive(Component)]
pub struct ToolbarStory;
impl ToolbarStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ToolbarStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)
.child(Story::title_for::<_, Toolbar<V>>(cx))
.child(Story::title_for::<_, Toolbar<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(
Toolbar::new()

View File

@ -77,15 +77,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::{Div, Render};
use crate::Story;
use super::*;
#[derive(Component)]
pub struct TrafficLightsStory;
impl TrafficLightsStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for TrafficLightsStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, TrafficLights>(cx))
.child(Story::label(cx, "Default"))

View File

@ -1,7 +1,7 @@
use std::sync::Arc;
use chrono::DateTime;
use gpui2::{px, relative, rems, AppContext, Context, Size, View};
use gpui2::{px, relative, rems, Div, Render, Size, View, VisualContext};
use crate::{prelude::*, NotificationsPanel};
use crate::{
@ -44,7 +44,7 @@ pub struct Workspace {
}
impl Workspace {
pub fn new(cx: &mut AppContext) -> Self {
pub fn new(cx: &mut ViewContext<Self>) -> Self {
Self {
title_bar: TitleBar::view(cx, None),
editor_1: EditorPane::view(cx),
@ -170,15 +170,15 @@ impl Workspace {
cx.notify();
}
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.build_model(|cx| Self::new(cx));
let render = Self::render;
View::for_handle(state, render)
}
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|cx| Self::new(cx))
}
}
pub fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
impl Render for Workspace {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
let theme = theme(cx);
// HACK: This should happen inside of `debug_toggle_user_settings`, but
@ -355,9 +355,8 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::VisualContext;
use super::*;
use gpui2::VisualContext;
pub struct WorkspaceStory {
workspace: View<Workspace>,
@ -365,12 +364,17 @@ mod stories {
impl WorkspaceStory {
pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(
|cx| Self {
workspace: Workspace::view(cx),
},
|view, cx| view.workspace.clone(),
)
cx.build_view(|cx| Self {
workspace: Workspace::view(cx),
})
}
}
impl Render for WorkspaceStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div().child(self.workspace.clone())
}
}
}

View File

@ -43,15 +43,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct AvatarStory;
impl AvatarStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for AvatarStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Avatar>(cx))
.child(Story::label(cx, "Default"))

View File

@ -219,22 +219,21 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::rems;
use super::*;
use crate::{h_stack, v_stack, LabelColor, Story};
use gpui2::{rems, Div, Render};
use strum::IntoEnumIterator;
use crate::{h_stack, v_stack, LabelColor, Story};
use super::*;
#[derive(Component)]
pub struct ButtonStory;
impl ButtonStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for ButtonStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let states = InteractionState::iter();
Story::container(cx)
.child(Story::title_for::<_, Button<V>>(cx))
.child(Story::title_for::<_, Button<Self>>(cx))
.child(
div()
.flex()

View File

@ -46,17 +46,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::{Button, Story};
use super::*;
use crate::{Button, Story};
use gpui2::{Div, Render};
#[derive(Component)]
pub struct DetailsStory;
impl DetailsStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for DetailsStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Details<V>>(cx))
.child(Story::title_for::<_, Details<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(Details::new("The quick brown fox jumps over the lazy dog"))
.child(Story::label(cx, "With meta"))

View File

@ -191,17 +191,19 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use gpui2::{Div, Render};
use strum::IntoEnumIterator;
use crate::Story;
use super::*;
#[derive(Component)]
pub struct IconStory;
impl IconStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for IconStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let icons = Icon::iter();
Story::container(cx)

View File

@ -112,15 +112,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct InputStory;
impl InputStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for InputStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Input>(cx))
.child(Story::label(cx, "Default"))

View File

@ -197,15 +197,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use crate::Story;
use super::*;
use crate::Story;
use gpui2::{Div, Render};
#[derive(Component)]
pub struct LabelStory;
impl LabelStory {
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
impl Render for LabelStory {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Label>(cx))
.child(Story::label(cx, "Default"))

View File

@ -1,7 +1,7 @@
use std::path::PathBuf;
use std::str::FromStr;
use gpui2::{AppContext, WindowContext};
use gpui2::ViewContext;
use rand::Rng;
use theme2::Theme;
@ -628,7 +628,7 @@ pub fn example_editor_actions() -> Vec<PaletteItem> {
]
}
pub fn empty_editor_example(cx: &mut WindowContext) -> EditorPane {
pub fn empty_editor_example(cx: &mut ViewContext<EditorPane>) -> EditorPane {
EditorPane::new(
cx,
static_tabs_example(),
@ -642,7 +642,7 @@ pub fn empty_buffer_example() -> Buffer {
Buffer::new("empty-buffer").set_rows(Some(BufferRows::default()))
}
pub fn hello_world_rust_editor_example(cx: &mut WindowContext) -> EditorPane {
pub fn hello_world_rust_editor_example(cx: &mut ViewContext<EditorPane>) -> EditorPane {
let theme = theme(cx);
EditorPane::new(
@ -781,7 +781,7 @@ pub fn hello_world_rust_buffer_rows(theme: &Theme) -> Vec<BufferRow> {
]
}
pub fn hello_world_rust_editor_with_status_example(cx: &mut AppContext) -> EditorPane {
pub fn hello_world_rust_editor_with_status_example(cx: &mut ViewContext<EditorPane>) -> EditorPane {
let theme = theme(cx);
EditorPane::new(