Compare commits
4 commits
main
...
element-tr
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e3da2e691c | ||
![]() |
317acbf1d7 | ||
![]() |
b52db5c5e6 | ||
![]() |
30280ab897 |
25 changed files with 417 additions and 417 deletions
84
Cargo.lock
generated
84
Cargo.lock
generated
|
@ -5953,61 +5953,6 @@ dependencies = [
|
|||
"util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "project2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"backtrace",
|
||||
"client2",
|
||||
"clock",
|
||||
"collections",
|
||||
"copilot2",
|
||||
"ctor",
|
||||
"db2",
|
||||
"env_logger 0.9.3",
|
||||
"fs",
|
||||
"fsevent",
|
||||
"futures 0.3.28",
|
||||
"fuzzy2",
|
||||
"git",
|
||||
"git2",
|
||||
"globset",
|
||||
"gpui2",
|
||||
"ignore",
|
||||
"itertools 0.10.5",
|
||||
"language2",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"lsp2",
|
||||
"node_runtime",
|
||||
"parking_lot 0.11.2",
|
||||
"postage",
|
||||
"prettier",
|
||||
"pretty_assertions",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"rpc",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings2",
|
||||
"sha2 0.10.7",
|
||||
"similar",
|
||||
"smol",
|
||||
"sum_tree",
|
||||
"tempdir",
|
||||
"terminal",
|
||||
"text",
|
||||
"thiserror",
|
||||
"toml 0.5.11",
|
||||
"unindent",
|
||||
"util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "project_panel"
|
||||
version = "0.1.0"
|
||||
|
@ -8374,35 +8319,6 @@ dependencies = [
|
|||
"util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"alacritty_terminal",
|
||||
"anyhow",
|
||||
"db2",
|
||||
"dirs 4.0.0",
|
||||
"futures 0.3.28",
|
||||
"gpui2",
|
||||
"itertools 0.10.5",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"mio-extras",
|
||||
"ordered-float 2.10.0",
|
||||
"procinfo",
|
||||
"rand 0.8.5",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"settings2",
|
||||
"shellexpand",
|
||||
"smallvec",
|
||||
"smol",
|
||||
"theme2",
|
||||
"thiserror",
|
||||
"util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_view"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -62,7 +62,7 @@ members = [
|
|||
"crates/plugin_runtime",
|
||||
"crates/prettier",
|
||||
"crates/project",
|
||||
"crates/project2",
|
||||
# "crates/project2",
|
||||
"crates/project_panel",
|
||||
"crates/project_symbols",
|
||||
"crates/recent_projects",
|
||||
|
@ -78,7 +78,7 @@ members = [
|
|||
"crates/storybook2",
|
||||
"crates/sum_tree",
|
||||
"crates/terminal",
|
||||
"crates/terminal2",
|
||||
#"crates/terminal2",
|
||||
"crates/text",
|
||||
"crates/theme",
|
||||
"crates/theme2",
|
||||
|
|
|
@ -178,7 +178,7 @@ pub struct AppContext {
|
|||
pub(crate) svg_renderer: SvgRenderer,
|
||||
pub(crate) image_cache: ImageCache,
|
||||
pub(crate) text_style_stack: Vec<TextStyleRefinement>,
|
||||
pub(crate) globals_by_type: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
|
||||
pub(crate) globals_by_type: HashMap<TypeId, AnyBox>,
|
||||
pub(crate) unit_entity: Handle<()>,
|
||||
pub(crate) entities: EntityMap,
|
||||
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
||||
|
@ -574,7 +574,7 @@ impl AppContext {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn lease_global<G: 'static + Send + Sync>(&mut self) -> Box<G> {
|
||||
pub(crate) fn lease_global<G: Any>(&mut self) -> Box<G> {
|
||||
self.globals_by_type
|
||||
.remove(&TypeId::of::<G>())
|
||||
.ok_or_else(|| anyhow!("no global registered of type {}", type_name::<G>()))
|
||||
|
@ -583,7 +583,7 @@ impl AppContext {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn restore_global<G: 'static + Send + Sync>(&mut self, global: Box<G>) {
|
||||
pub(crate) fn restore_global<G: Any>(&mut self, global: Box<G>) {
|
||||
let global_type = TypeId::of::<G>();
|
||||
self.push_effect(Effect::NotifyGlobalObservers { global_type });
|
||||
self.globals_by_type.insert(global_type, global);
|
||||
|
@ -639,7 +639,7 @@ impl AppContext {
|
|||
}
|
||||
|
||||
impl Context for AppContext {
|
||||
type EntityContext<'a, 'w, T: Send + Sync + 'static> = ModelContext<'a, T>;
|
||||
type EntityContext<'a, 'w, T> = ModelContext<'a, T>;
|
||||
type Result<T> = T;
|
||||
|
||||
fn entity<T: Send + Sync + 'static>(
|
||||
|
@ -653,7 +653,7 @@ impl Context for AppContext {
|
|||
})
|
||||
}
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
|
@ -723,11 +723,11 @@ impl MainThread<AppContext> {
|
|||
self.platform().open_url(url);
|
||||
}
|
||||
|
||||
pub fn open_window<S: 'static + Send + Sync>(
|
||||
pub fn open_window<V: 'static + Send + Sync>(
|
||||
&mut self,
|
||||
options: crate::WindowOptions,
|
||||
build_root_view: impl FnOnce(&mut WindowContext) -> View<S> + Send + 'static,
|
||||
) -> WindowHandle<S> {
|
||||
build_root_view: impl FnOnce(&mut WindowContext) -> View<V> + Send + 'static,
|
||||
) -> WindowHandle<V> {
|
||||
self.update(|cx| {
|
||||
let id = cx.windows.insert(None);
|
||||
let handle = WindowHandle::new(id);
|
||||
|
@ -739,7 +739,7 @@ impl MainThread<AppContext> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn update_global<G: 'static + Send + Sync, R>(
|
||||
pub fn update_global<G: Any, R>(
|
||||
&mut self,
|
||||
update: impl FnOnce(&mut G, &mut MainThread<AppContext>) -> R,
|
||||
) -> R {
|
||||
|
@ -756,7 +756,7 @@ pub(crate) enum Effect {
|
|||
},
|
||||
Emit {
|
||||
emitter: EntityId,
|
||||
event: Box<dyn Any + Send + Sync + 'static>,
|
||||
event: AnyBox,
|
||||
},
|
||||
FocusChanged {
|
||||
window_id: WindowId,
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct AsyncAppContext {
|
|||
}
|
||||
|
||||
impl Context for AsyncAppContext {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
|
||||
type EntityContext<'a, 'w, T> = ModelContext<'a, T>;
|
||||
type Result<T> = Result<T>;
|
||||
|
||||
fn entity<T: Send + Sync + 'static>(
|
||||
|
@ -29,7 +29,7 @@ impl Context for AsyncAppContext {
|
|||
Ok(lock.entity(build_entity))
|
||||
}
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
|
@ -213,18 +213,18 @@ impl AsyncWindowContext {
|
|||
}
|
||||
|
||||
impl Context for AsyncWindowContext {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
|
||||
type EntityContext<'a, 'w, T> = ViewContext<'a, 'w, T>;
|
||||
type Result<T> = Result<T>;
|
||||
|
||||
fn entity<R: Send + Sync + 'static>(
|
||||
fn entity<T: Send + Sync + 'static>(
|
||||
&mut self,
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
|
||||
) -> Result<Handle<R>> {
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||
) -> Result<Handle<T>> {
|
||||
self.app
|
||||
.update_window(self.window, |cx| cx.entity(build_entity))
|
||||
}
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
|
|
|
@ -30,7 +30,7 @@ impl Display for EntityId {
|
|||
}
|
||||
|
||||
pub(crate) struct EntityMap {
|
||||
entities: SecondaryMap<EntityId, Box<dyn Any + Send + Sync>>,
|
||||
entities: SecondaryMap<EntityId, Box<dyn Any>>,
|
||||
ref_counts: Arc<RwLock<EntityRefCounts>>,
|
||||
}
|
||||
|
||||
|
@ -51,24 +51,20 @@ impl EntityMap {
|
|||
}
|
||||
|
||||
/// Reserve a slot for an entity, which you can subsequently use with `insert`.
|
||||
pub fn reserve<T: 'static + Send + Sync>(&self) -> Slot<T> {
|
||||
pub fn reserve<T: 'static>(&self) -> Slot<T> {
|
||||
let id = self.ref_counts.write().counts.insert(1.into());
|
||||
Slot(Handle::new(id, Arc::downgrade(&self.ref_counts)))
|
||||
}
|
||||
|
||||
/// Insert an entity into a slot obtained by calling `reserve`.
|
||||
pub fn insert<T: 'static + Any + Send + Sync>(
|
||||
&mut self,
|
||||
slot: Slot<T>,
|
||||
entity: T,
|
||||
) -> Handle<T> {
|
||||
pub fn insert<T: Any>(&mut self, slot: Slot<T>, entity: T) -> Handle<T> {
|
||||
let handle = slot.0;
|
||||
self.entities.insert(handle.entity_id, Box::new(entity));
|
||||
handle
|
||||
}
|
||||
|
||||
/// Move an entity to the stack.
|
||||
pub fn lease<'a, T: 'static + Send + Sync>(&mut self, handle: &'a Handle<T>) -> Lease<'a, T> {
|
||||
pub fn lease<'a, T>(&mut self, handle: &'a Handle<T>) -> Lease<'a, T> {
|
||||
let entity = Some(
|
||||
self.entities
|
||||
.remove(handle.entity_id)
|
||||
|
@ -80,16 +76,16 @@ impl EntityMap {
|
|||
}
|
||||
|
||||
/// Return an entity after moving it to the stack.
|
||||
pub fn end_lease<T: 'static + Send + Sync>(&mut self, mut lease: Lease<T>) {
|
||||
pub fn end_lease<T>(&mut self, mut lease: Lease<T>) {
|
||||
self.entities
|
||||
.insert(lease.handle.entity_id, lease.entity.take().unwrap());
|
||||
}
|
||||
|
||||
pub fn read<T: 'static + Send + Sync>(&self, handle: &Handle<T>) -> &T {
|
||||
pub fn read<T>(&self, handle: &Handle<T>) -> &T {
|
||||
self.entities[handle.entity_id].downcast_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn weak_handle<T: 'static + Send + Sync>(&self, id: EntityId) -> WeakHandle<T> {
|
||||
pub fn weak_handle<T>(&self, id: EntityId) -> WeakHandle<T> {
|
||||
WeakHandle {
|
||||
any_handle: AnyWeakHandle {
|
||||
entity_id: id,
|
||||
|
@ -100,7 +96,7 @@ impl EntityMap {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn take_dropped(&mut self) -> Vec<(EntityId, Box<dyn Any + Send + Sync>)> {
|
||||
pub fn take_dropped(&mut self) -> Vec<(EntityId, Box<dyn Any>)> {
|
||||
let dropped_entity_ids = mem::take(&mut self.ref_counts.write().dropped_entity_ids);
|
||||
dropped_entity_ids
|
||||
.into_iter()
|
||||
|
@ -109,15 +105,12 @@ impl EntityMap {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Lease<'a, T: Send + Sync> {
|
||||
pub struct Lease<'a, T> {
|
||||
entity: Option<Box<T>>,
|
||||
pub handle: &'a Handle<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> core::ops::Deref for Lease<'a, T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
impl<'a, T> core::ops::Deref for Lease<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
@ -125,19 +118,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> core::ops::DerefMut for Lease<'a, T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
impl<'a, T> core::ops::DerefMut for Lease<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.entity.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for Lease<'a, T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
impl<'a, T> Drop for Lease<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.entity.is_some() {
|
||||
// We don't panic here, because other panics can cause us to drop the lease without ending it cleanly.
|
||||
|
@ -147,7 +134,7 @@ where
|
|||
}
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
pub struct Slot<T: Send + Sync + 'static>(Handle<T>);
|
||||
pub struct Slot<T>(Handle<T>);
|
||||
|
||||
pub struct AnyHandle {
|
||||
pub(crate) entity_id: EntityId,
|
||||
|
@ -178,7 +165,7 @@ impl AnyHandle {
|
|||
|
||||
pub fn downcast<T>(&self) -> Option<Handle<T>>
|
||||
where
|
||||
T: 'static + Send + Sync,
|
||||
T: Any,
|
||||
{
|
||||
if TypeId::of::<T>() == self.entity_type {
|
||||
Some(Handle {
|
||||
|
@ -231,10 +218,7 @@ impl Drop for AnyHandle {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> From<Handle<T>> for AnyHandle
|
||||
where
|
||||
T: 'static + Send + Sync,
|
||||
{
|
||||
impl<T> From<Handle<T>> for AnyHandle {
|
||||
fn from(handle: Handle<T>) -> Self {
|
||||
handle.any_handle
|
||||
}
|
||||
|
@ -255,14 +239,14 @@ impl PartialEq for AnyHandle {
|
|||
impl Eq for AnyHandle {}
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
pub struct Handle<T: Send + Sync> {
|
||||
pub struct Handle<T> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
any_handle: AnyHandle,
|
||||
entity_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: 'static + Send + Sync> Handle<T> {
|
||||
impl<T> Handle<T> {
|
||||
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self {
|
||||
Self {
|
||||
any_handle: AnyHandle::new(id, TypeId::of::<T>(), entity_map),
|
||||
|
@ -295,7 +279,7 @@ impl<T: 'static + Send + Sync> Handle<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync> Clone for Handle<T> {
|
||||
impl<T> Clone for Handle<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
any_handle: self.any_handle.clone(),
|
||||
|
@ -304,7 +288,7 @@ impl<T: Send + Sync> Clone for Handle<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static + Send + Sync> std::fmt::Debug for Handle<T> {
|
||||
impl<T> std::fmt::Debug for Handle<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -315,19 +299,19 @@ impl<T: 'static + Send + Sync> std::fmt::Debug for Handle<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Hash for Handle<T> {
|
||||
impl<T> Hash for Handle<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.any_handle.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> PartialEq for Handle<T> {
|
||||
impl<T> PartialEq for Handle<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.any_handle == other.any_handle
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Eq for Handle<T> {}
|
||||
impl<T> Eq for Handle<T> {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AnyWeakHandle {
|
||||
|
@ -436,16 +420,16 @@ impl<T: Send + Sync + 'static> WeakHandle<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Hash for WeakHandle<T> {
|
||||
impl<T> Hash for WeakHandle<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.any_handle.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> PartialEq for WeakHandle<T> {
|
||||
impl<T> PartialEq for WeakHandle<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.any_handle == other.any_handle
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Eq for WeakHandle<T> {}
|
||||
impl<T> Eq for WeakHandle<T> {}
|
||||
|
|
|
@ -15,7 +15,7 @@ pub struct ModelContext<'a, T> {
|
|||
entity_id: EntityId,
|
||||
}
|
||||
|
||||
impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
impl<'a, T> ModelContext<'a, T> {
|
||||
pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self {
|
||||
Self {
|
||||
app: Reference::Mutable(app),
|
||||
|
@ -38,7 +38,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
|||
self.app.entities.weak_handle(self.entity_id)
|
||||
}
|
||||
|
||||
pub fn observe<E: Send + Sync + 'static>(
|
||||
pub fn observe<E>(
|
||||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_notify: impl Fn(&mut T, Handle<E>, &mut ModelContext<'_, T>) + Send + Sync + 'static,
|
||||
|
@ -58,7 +58,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<E: EventEmitter + Send + Sync + 'static>(
|
||||
pub fn subscribe<E: EventEmitter>(
|
||||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_event: impl Fn(&mut T, Handle<E>, &E::Event, &mut ModelContext<'_, T>)
|
||||
|
@ -95,7 +95,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn observe_release<E: Send + Sync + 'static>(
|
||||
pub fn observe_release<E>(
|
||||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_release: impl Fn(&mut T, &mut E, &mut ModelContext<'_, T>) + Send + Sync + 'static,
|
||||
|
@ -176,7 +176,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> {
|
||||
impl<'a, T: EventEmitter> ModelContext<'a, T> {
|
||||
pub fn emit(&mut self, event: T::Event) {
|
||||
self.app.pending_effects.push_back(Effect::Emit {
|
||||
emitter: self.entity_id,
|
||||
|
@ -186,7 +186,7 @@ impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> {
|
|||
}
|
||||
|
||||
impl<'a, T: 'static> Context for ModelContext<'a, T> {
|
||||
type EntityContext<'b, 'c, U: Send + Sync + 'static> = ModelContext<'b, U>;
|
||||
type EntityContext<'b, 'c, U> = ModelContext<'b, U>;
|
||||
type Result<U> = U;
|
||||
|
||||
fn entity<U: Send + Sync + 'static>(
|
||||
|
@ -196,7 +196,7 @@ impl<'a, T: 'static> Context for ModelContext<'a, T> {
|
|||
self.app.entity(build_entity)
|
||||
}
|
||||
|
||||
fn update_entity<U: Send + Sync + 'static, R>(
|
||||
fn update_entity<U, R>(
|
||||
&mut self,
|
||||
handle: &Handle<U>,
|
||||
update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
|
||||
|
|
|
@ -3,9 +3,9 @@ use derive_more::{Deref, DerefMut};
|
|||
pub(crate) use smallvec::SmallVec;
|
||||
use std::mem;
|
||||
|
||||
pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
|
||||
type ViewState: 'static + Send + Sync;
|
||||
type ElementState: 'static + Send + Sync;
|
||||
pub trait Element: IntoAnyElement<Self::ViewState> {
|
||||
type ViewState;
|
||||
type ElementState;
|
||||
|
||||
fn id(&self) -> Option<ElementId>;
|
||||
|
||||
|
@ -59,7 +59,7 @@ pub trait ParentElement: Element {
|
|||
}
|
||||
}
|
||||
|
||||
trait ElementObject<V>: 'static + Send + Sync {
|
||||
trait ElementObject<V> {
|
||||
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||
fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
|
||||
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||
|
@ -173,7 +173,7 @@ where
|
|||
|
||||
pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
|
||||
|
||||
impl<V: 'static + Send + Sync> AnyElement<V> {
|
||||
impl<V> AnyElement<V> {
|
||||
pub fn new<E: Element<ViewState = V>>(element: E) -> Self {
|
||||
AnyElement(Box::new(RenderedElement::new(element)))
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@ mod div;
|
|||
mod img;
|
||||
mod svg;
|
||||
mod text;
|
||||
mod trampoline;
|
||||
|
||||
pub use div::*;
|
||||
pub use img::*;
|
||||
pub use svg::*;
|
||||
pub use text::*;
|
||||
pub use trampoline::*;
|
||||
|
|
|
@ -9,7 +9,7 @@ use refineable::Refineable;
|
|||
use smallvec::SmallVec;
|
||||
|
||||
pub struct Div<
|
||||
V: 'static + Send + Sync,
|
||||
V,
|
||||
I: ElementInteraction<V> = StatelessInteraction<V>,
|
||||
F: ElementFocus<V> = FocusDisabled,
|
||||
> {
|
||||
|
@ -21,8 +21,8 @@ pub struct Div<
|
|||
}
|
||||
|
||||
pub fn div<V>() -> Div<V, StatelessInteraction<V>, FocusDisabled>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
// where
|
||||
// V: 'static + Send + Sync,
|
||||
{
|
||||
Div {
|
||||
interaction: StatelessInteraction::default(),
|
||||
|
@ -36,7 +36,6 @@ where
|
|||
impl<V, F> Div<V, StatelessInteraction<V>, F>
|
||||
where
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
pub fn id(self, id: impl Into<ElementId>) -> Div<V, StatefulInteraction<V>, F> {
|
||||
Div {
|
||||
|
@ -53,7 +52,6 @@ impl<V, I, F> Div<V, I, F>
|
|||
where
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
pub fn group(mut self, group: impl Into<SharedString>) -> Self {
|
||||
self.group = Some(group.into());
|
||||
|
@ -108,10 +106,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> Div<V, StatefulInteraction<V>, FocusDisabled>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> Div<V, StatefulInteraction<V>, FocusDisabled> {
|
||||
pub fn focusable(self) -> Div<V, StatefulInteraction<V>, FocusEnabled<V>> {
|
||||
Div {
|
||||
interaction: self.interaction,
|
||||
|
@ -152,10 +147,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> Div<V, StatelessInteraction<V>, FocusDisabled>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> Div<V, StatelessInteraction<V>, FocusDisabled> {
|
||||
pub fn track_focus(
|
||||
self,
|
||||
handle: &FocusHandle,
|
||||
|
@ -173,7 +165,6 @@ where
|
|||
impl<V, I> Focusable for Div<V, I, FocusEnabled<V>>
|
||||
where
|
||||
I: ElementInteraction<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
fn focus_listeners(&mut self) -> &mut FocusListeners<V> {
|
||||
&mut self.focus.focus_listeners
|
||||
|
@ -203,7 +194,6 @@ impl<V, I, F> Element for Div<V, I, F>
|
|||
where
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
type ViewState = V;
|
||||
type ElementState = DivState;
|
||||
|
@ -319,7 +309,6 @@ impl<V, I, F> IntoAnyElement<V> for Div<V, I, F>
|
|||
where
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
fn into_any(self) -> AnyElement<V> {
|
||||
AnyElement::new(self)
|
||||
|
@ -330,7 +319,6 @@ impl<V, I, F> ParentElement for Div<V, I, F>
|
|||
where
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
|
||||
&mut self.children
|
||||
|
@ -341,7 +329,6 @@ impl<V, I, F> Styled for Div<V, I, F>
|
|||
where
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
fn style(&mut self) -> &mut StyleRefinement {
|
||||
&mut self.base_style
|
||||
|
@ -352,7 +339,6 @@ impl<V, I, F> StatelessInteractive for Div<V, I, F>
|
|||
where
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
fn stateless_interaction(&mut self) -> &mut StatelessInteraction<V> {
|
||||
self.interaction.as_stateless_mut()
|
||||
|
@ -362,7 +348,6 @@ where
|
|||
impl<V, F> StatefulInteractive for Div<V, StatefulInteraction<V>, F>
|
||||
where
|
||||
F: ElementFocus<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
fn stateful_interaction(&mut self) -> &mut StatefulInteraction<Self::ViewState> {
|
||||
&mut self.interaction
|
||||
|
|
|
@ -8,7 +8,7 @@ use futures::FutureExt;
|
|||
use util::ResultExt;
|
||||
|
||||
pub struct Img<
|
||||
V: 'static + Send + Sync,
|
||||
V,
|
||||
I: ElementInteraction<V> = StatelessInteraction<V>,
|
||||
F: ElementFocus<V> = FocusDisabled,
|
||||
> {
|
||||
|
@ -17,10 +17,7 @@ pub struct Img<
|
|||
grayscale: bool,
|
||||
}
|
||||
|
||||
pub fn img<V>() -> Img<V, StatelessInteraction<V>, FocusDisabled>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
pub fn img<V>() -> Img<V, StatelessInteraction<V>, FocusDisabled> {
|
||||
Img {
|
||||
base: div(),
|
||||
uri: None,
|
||||
|
@ -30,7 +27,6 @@ where
|
|||
|
||||
impl<V, I, F> Img<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -47,7 +43,6 @@ where
|
|||
|
||||
impl<V, F> Img<V, StatelessInteraction<V>, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
pub fn id(self, id: impl Into<ElementId>) -> Img<V, StatefulInteraction<V>, F> {
|
||||
|
@ -61,7 +56,6 @@ where
|
|||
|
||||
impl<V, I, F> IntoAnyElement<V> for Img<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -72,7 +66,6 @@ where
|
|||
|
||||
impl<V, I, F> Element for Img<V, I, F>
|
||||
where
|
||||
V: Send + Sync + 'static,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -141,7 +134,6 @@ where
|
|||
|
||||
impl<V, I, F> Styled for Img<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -152,7 +144,6 @@ where
|
|||
|
||||
impl<V, I, F> StatelessInteractive for Img<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -163,7 +154,6 @@ where
|
|||
|
||||
impl<V, F> StatefulInteractive for Img<V, StatefulInteraction<V>, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
fn stateful_interaction(&mut self) -> &mut StatefulInteraction<Self::ViewState> {
|
||||
|
@ -173,7 +163,6 @@ where
|
|||
|
||||
impl<V, I> Focusable for Img<V, I, FocusEnabled<V>>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
{
|
||||
fn focus_listeners(&mut self) -> &mut FocusListeners<Self::ViewState> {
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
use util::ResultExt;
|
||||
|
||||
pub struct Svg<
|
||||
V: 'static + Send + Sync,
|
||||
V,
|
||||
I: ElementInteraction<V> = StatelessInteraction<V>,
|
||||
F: ElementFocus<V> = FocusDisabled,
|
||||
> {
|
||||
|
@ -15,10 +15,7 @@ pub struct Svg<
|
|||
path: Option<SharedString>,
|
||||
}
|
||||
|
||||
pub fn svg<V>() -> Svg<V, StatelessInteraction<V>, FocusDisabled>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
pub fn svg<V>() -> Svg<V, StatelessInteraction<V>, FocusDisabled> {
|
||||
Svg {
|
||||
base: div(),
|
||||
path: None,
|
||||
|
@ -27,7 +24,6 @@ where
|
|||
|
||||
impl<V, I, F> Svg<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -39,7 +35,6 @@ where
|
|||
|
||||
impl<V, F> Svg<V, StatelessInteraction<V>, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
pub fn id(self, id: impl Into<ElementId>) -> Svg<V, StatefulInteraction<V>, F> {
|
||||
|
@ -52,7 +47,6 @@ where
|
|||
|
||||
impl<V, I, F> IntoAnyElement<V> for Svg<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -63,7 +57,6 @@ where
|
|||
|
||||
impl<V, I, F> Element for Svg<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -115,7 +108,6 @@ where
|
|||
|
||||
impl<V, I, F> Styled for Svg<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -126,7 +118,6 @@ where
|
|||
|
||||
impl<V, I, F> StatelessInteractive for Svg<V, I, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
|
@ -137,7 +128,6 @@ where
|
|||
|
||||
impl<V, F> StatefulInteractive for Svg<V, StatefulInteraction<V>, F>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
F: ElementFocus<V>,
|
||||
{
|
||||
fn stateful_interaction(&mut self) -> &mut StatefulInteraction<Self::ViewState> {
|
||||
|
@ -147,7 +137,6 @@ where
|
|||
|
||||
impl<V, I> Focusable for Svg<V, I, FocusEnabled<V>>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
I: ElementInteraction<V>,
|
||||
{
|
||||
fn focus_listeners(&mut self) -> &mut FocusListeners<Self::ViewState> {
|
||||
|
|
|
@ -7,8 +7,8 @@ use smallvec::SmallVec;
|
|||
use std::{marker::PhantomData, sync::Arc};
|
||||
use util::ResultExt;
|
||||
|
||||
impl<S: 'static + Send + Sync> IntoAnyElement<S> for SharedString {
|
||||
fn into_any(self) -> AnyElement<S> {
|
||||
impl<V> IntoAnyElement<V> for SharedString {
|
||||
fn into_any(self) -> AnyElement<V> {
|
||||
Text {
|
||||
text: self,
|
||||
state_type: PhantomData,
|
||||
|
@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync> IntoAnyElement<S> for SharedString {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> IntoAnyElement<V> for &'static str {
|
||||
impl<V> IntoAnyElement<V> for &'static str {
|
||||
fn into_any(self) -> AnyElement<V> {
|
||||
Text {
|
||||
text: self.into(),
|
||||
|
@ -29,7 +29,7 @@ impl<V: 'static + Send + Sync> IntoAnyElement<V> for &'static str {
|
|||
|
||||
// TODO: Figure out how to pass `String` to `child` without this.
|
||||
// This impl doesn't exist in the `gpui2` crate.
|
||||
impl<S: 'static + Send + Sync> IntoAnyElement<S> for String {
|
||||
impl<S> IntoAnyElement<S> for String {
|
||||
fn into_any(self) -> AnyElement<S> {
|
||||
Text {
|
||||
text: self.into(),
|
||||
|
@ -44,13 +44,13 @@ pub struct Text<V> {
|
|||
state_type: PhantomData<V>,
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> IntoAnyElement<V> for Text<V> {
|
||||
impl<V> IntoAnyElement<V> for Text<V> {
|
||||
fn into_any(self) -> AnyElement<V> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> Element for Text<V> {
|
||||
impl<V> Element for Text<V> {
|
||||
type ViewState = V;
|
||||
type ElementState = Arc<Mutex<Option<TextElementState>>>;
|
||||
|
||||
|
|
65
crates/gpui2/src/elements/trampoline.rs
Normal file
65
crates/gpui2/src/elements/trampoline.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use crate::{Element, ViewContext, AnyElement, IntoAnyElement};
|
||||
|
||||
pub trait TemporaryRenderTraitDontWorryAboutIt<S> {
|
||||
fn render(self, cx: &mut ViewContext<S>) -> AnyElement<S>;
|
||||
}
|
||||
|
||||
|
||||
struct IntoAnyElementTrampolineName<S, E: TemporaryRenderTraitDontWorryAboutIt<S>> {
|
||||
contents: Option<E>,
|
||||
phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, E: TemporaryRenderTraitDontWorryAboutIt<S>> IntoAnyElementTrampolineName<S, E> {
|
||||
fn new(contents: E) -> Self {
|
||||
IntoAnyElementTrampolineName {
|
||||
contents: Some(contents),
|
||||
phantom: std::marker::PhantomData,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, E: TemporaryRenderTraitDontWorryAboutIt<S>> Element for IntoAnyElementTrampolineName<S, E> {
|
||||
type ViewState = S;
|
||||
|
||||
type ElementState = AnyElement<S>;
|
||||
|
||||
fn id(&self) -> Option<crate::ElementId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn initialize(
|
||||
&mut self,
|
||||
view_state: &mut Self::ViewState,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> Self::ElementState {
|
||||
self.contents.take().unwrap().render(cx)
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> crate::LayoutId {
|
||||
element_state.layout(view_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: crate::Bounds<crate::Pixels>,
|
||||
view_state: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
element_state.paint(view_state, cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, E: TemporaryRenderTraitDontWorryAboutIt<S>> IntoAnyElement<S> for IntoAnyElementTrampolineName<S, E> {
|
||||
fn into_any(self) -> AnyElement<S> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
|
@ -135,7 +135,7 @@ pub trait Focusable: Element {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ElementFocus<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||
pub trait ElementFocus<V> {
|
||||
fn as_focusable(&self) -> Option<&FocusEnabled<V>>;
|
||||
fn as_focusable_mut(&mut self) -> Option<&mut FocusEnabled<V>>;
|
||||
|
||||
|
@ -200,7 +200,7 @@ pub trait ElementFocus<V: 'static + Send + Sync>: 'static + Send + Sync {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct FocusEnabled<V: 'static + Send + Sync> {
|
||||
pub struct FocusEnabled<V> {
|
||||
pub focus_handle: Option<FocusHandle>,
|
||||
pub focus_listeners: FocusListeners<V>,
|
||||
pub focus_style: StyleRefinement,
|
||||
|
@ -208,10 +208,7 @@ pub struct FocusEnabled<V: 'static + Send + Sync> {
|
|||
pub in_focus_style: StyleRefinement,
|
||||
}
|
||||
|
||||
impl<V> FocusEnabled<V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> FocusEnabled<V> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
focus_handle: None,
|
||||
|
@ -233,10 +230,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> ElementFocus<V> for FocusEnabled<V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> ElementFocus<V> for FocusEnabled<V> {
|
||||
fn as_focusable(&self) -> Option<&FocusEnabled<V>> {
|
||||
Some(self)
|
||||
}
|
||||
|
@ -246,10 +240,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> From<FocusHandle> for FocusEnabled<V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> From<FocusHandle> for FocusEnabled<V> {
|
||||
fn from(value: FocusHandle) -> Self {
|
||||
Self {
|
||||
focus_handle: Some(value),
|
||||
|
@ -263,10 +254,7 @@ where
|
|||
|
||||
pub struct FocusDisabled;
|
||||
|
||||
impl<V> ElementFocus<V> for FocusDisabled
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> ElementFocus<V> for FocusDisabled {
|
||||
fn as_focusable(&self) -> Option<&FocusEnabled<V>> {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ use taffy::TaffyLayoutEngine;
|
|||
type AnyBox = Box<dyn Any + Send + Sync>;
|
||||
|
||||
pub trait Context {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync>;
|
||||
type EntityContext<'a, 'w, T>;
|
||||
type Result<T>;
|
||||
|
||||
fn entity<T: Send + Sync + 'static>(
|
||||
|
@ -74,7 +74,7 @@ pub trait Context {
|
|||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||
) -> Self::Result<Handle<T>>;
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
|
@ -105,10 +105,10 @@ impl<T> DerefMut for MainThread<T> {
|
|||
}
|
||||
|
||||
impl<C: Context> Context for MainThread<C> {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = MainThread<C::EntityContext<'a, 'w, T>>;
|
||||
type EntityContext<'a, 'w, T> = MainThread<C::EntityContext<'a, 'w, T>>;
|
||||
type Result<T> = C::Result<T>;
|
||||
|
||||
fn entity<T: Send + Sync + 'static>(
|
||||
fn entity<T: 'static + Send + Sync>(
|
||||
&mut self,
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||
) -> Self::Result<Handle<T>> {
|
||||
|
@ -123,7 +123,7 @@ impl<C: Context> Context for MainThread<C> {
|
|||
})
|
||||
}
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
|
|
|
@ -387,7 +387,7 @@ pub trait StatefulInteractive: StatelessInteractive {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||
pub trait ElementInteraction<V> {
|
||||
fn as_stateless(&self) -> &StatelessInteraction<V>;
|
||||
fn as_stateless_mut(&mut self) -> &mut StatelessInteraction<V>;
|
||||
fn as_stateful(&self) -> Option<&StatefulInteraction<V>>;
|
||||
|
@ -397,7 +397,10 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
|||
&mut self,
|
||||
cx: &mut ViewContext<V>,
|
||||
f: impl FnOnce(&mut ViewContext<V>) -> R,
|
||||
) -> R {
|
||||
) -> R
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
if let Some(stateful) = self.as_stateful_mut() {
|
||||
cx.with_element_id(stateful.id.clone(), |global_id, cx| {
|
||||
stateful.key_listeners.push((
|
||||
|
@ -433,7 +436,9 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
|||
bounds: Bounds<Pixels>,
|
||||
element_state: &InteractiveElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
) where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
let mouse_position = cx.mouse_position();
|
||||
let stateless = self.as_stateless();
|
||||
if let Some(group_hover) = stateless.group_hover_style.as_ref() {
|
||||
|
@ -487,7 +492,9 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
|||
overflow: Point<Overflow>,
|
||||
element_state: &mut InteractiveElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
) where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
let stateless = self.as_stateless();
|
||||
for listener in stateless.mouse_down_listeners.iter().cloned() {
|
||||
cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
|
||||
|
@ -681,7 +688,7 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
|||
}
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
pub struct StatefulInteraction<V: 'static + Send + Sync> {
|
||||
pub struct StatefulInteraction<V> {
|
||||
pub id: ElementId,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
|
@ -692,10 +699,7 @@ pub struct StatefulInteraction<V: 'static + Send + Sync> {
|
|||
drag_listener: Option<DragListener<V>>,
|
||||
}
|
||||
|
||||
impl<V> ElementInteraction<V> for StatefulInteraction<V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> ElementInteraction<V> for StatefulInteraction<V> {
|
||||
fn as_stateful(&self) -> Option<&StatefulInteraction<V>> {
|
||||
Some(self)
|
||||
}
|
||||
|
@ -713,10 +717,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> From<ElementId> for StatefulInteraction<V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> From<ElementId> for StatefulInteraction<V> {
|
||||
fn from(id: ElementId) -> Self {
|
||||
Self {
|
||||
id,
|
||||
|
@ -745,10 +746,7 @@ pub struct StatelessInteraction<V> {
|
|||
drop_listeners: SmallVec<[(TypeId, Arc<DropListener<V>>); 2]>,
|
||||
}
|
||||
|
||||
impl<V> StatelessInteraction<V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> StatelessInteraction<V> {
|
||||
pub fn into_stateful(self, id: impl Into<ElementId>) -> StatefulInteraction<V> {
|
||||
StatefulInteraction {
|
||||
id: id.into(),
|
||||
|
@ -840,10 +838,7 @@ impl<V> Default for StatelessInteraction<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> ElementInteraction<V> for StatelessInteraction<V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
impl<V> ElementInteraction<V> for StatelessInteraction<V> {
|
||||
fn as_stateful(&self) -> Option<&StatefulInteraction<V>> {
|
||||
None
|
||||
}
|
||||
|
@ -918,9 +913,7 @@ pub struct ClickEvent {
|
|||
|
||||
pub struct Drag<S, R, V, E>
|
||||
where
|
||||
S: 'static + Send + Sync,
|
||||
R: Fn(&mut V, &mut ViewContext<V>) -> E,
|
||||
V: 'static + Send + Sync,
|
||||
E: Element<ViewState = V>,
|
||||
{
|
||||
pub state: S,
|
||||
|
@ -930,9 +923,7 @@ where
|
|||
|
||||
impl<S, R, V, E> Drag<S, R, V, E>
|
||||
where
|
||||
S: 'static + Send + Sync,
|
||||
R: Fn(&mut V, &mut ViewContext<V>) -> E + Send + Sync,
|
||||
V: 'static + Send + Sync,
|
||||
E: Element<ViewState = V>,
|
||||
{
|
||||
pub fn new(state: S, render_drag_handle: R) -> Self {
|
||||
|
|
|
@ -6,12 +6,12 @@ use crate::{
|
|||
};
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
pub struct View<V: Send + Sync> {
|
||||
pub struct View<V> {
|
||||
state: Handle<V>,
|
||||
render: Arc<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + Sync + 'static>,
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> View<V> {
|
||||
impl<V> View<V> {
|
||||
pub fn into_any(self) -> AnyView {
|
||||
AnyView {
|
||||
view: Arc::new(Mutex::new(self)),
|
||||
|
@ -19,7 +19,7 @@ impl<V: 'static + Send + Sync> View<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: Send + Sync> Clone for View<V> {
|
||||
impl<V> Clone for View<V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
state: self.state.clone(),
|
||||
|
@ -42,9 +42,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync, ParentViewState: 'static + Send + Sync>
|
||||
IntoAnyElement<ParentViewState> for View<V>
|
||||
{
|
||||
impl<V, ParentViewState> IntoAnyElement<ParentViewState> for View<V> {
|
||||
fn into_any(self) -> AnyElement<ParentViewState> {
|
||||
AnyElement::new(EraseViewState {
|
||||
view: self,
|
||||
|
@ -53,7 +51,7 @@ impl<V: 'static + Send + Sync, ParentViewState: 'static + Send + Sync>
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> Element for View<V> {
|
||||
impl<V> Element for View<V> {
|
||||
type ViewState = ();
|
||||
type ElementState = AnyElement<V>;
|
||||
|
||||
|
@ -94,26 +92,18 @@ impl<V: 'static + Send + Sync> Element for View<V> {
|
|||
}
|
||||
}
|
||||
|
||||
struct EraseViewState<V: 'static + Send + Sync, ParentV> {
|
||||
struct EraseViewState<V, ParentV> {
|
||||
view: View<V>,
|
||||
parent_view_state_type: PhantomData<ParentV>,
|
||||
}
|
||||
|
||||
impl<V, ParentV> IntoAnyElement<ParentV> for EraseViewState<V, ParentV>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
ParentV: 'static + Send + Sync,
|
||||
{
|
||||
impl<V, ParentV> IntoAnyElement<ParentV> for EraseViewState<V, ParentV> {
|
||||
fn into_any(self) -> AnyElement<ParentV> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, ParentV> Element for EraseViewState<V, ParentV>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
ParentV: 'static + Send + Sync,
|
||||
{
|
||||
impl<V, ParentV> Element for EraseViewState<V, ParentV> {
|
||||
type ViewState = ParentV;
|
||||
type ElementState = AnyBox;
|
||||
|
||||
|
@ -150,14 +140,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait ViewObject: 'static + Send + Sync {
|
||||
trait ViewObject {
|
||||
fn entity_id(&self) -> EntityId;
|
||||
fn initialize(&mut self, cx: &mut WindowContext) -> AnyBox;
|
||||
fn layout(&mut self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
|
||||
fn paint(&mut self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
|
||||
}
|
||||
|
||||
impl<V: Send + Sync + 'static> ViewObject for View<V> {
|
||||
impl<V: 'static + Send + Sync> ViewObject for View<V> {
|
||||
fn entity_id(&self) -> EntityId {
|
||||
self.state.entity_id
|
||||
}
|
||||
|
|
|
@ -1129,7 +1129,7 @@ impl<'a, 'w> MainThread<WindowContext<'a, 'w>> {
|
|||
}
|
||||
|
||||
impl Context for WindowContext<'_, '_> {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
|
||||
type EntityContext<'a, 'w, T> = ViewContext<'a, 'w, T>;
|
||||
type Result<T> = T;
|
||||
|
||||
fn entity<T: Send + Sync + 'static>(
|
||||
|
@ -1145,7 +1145,7 @@ impl Context for WindowContext<'_, '_> {
|
|||
self.entities.insert(slot, entity)
|
||||
}
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
|
@ -1340,7 +1340,7 @@ impl<S> BorrowWindow for ViewContext<'_, '_, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
||||
impl<'a, 'w, V> ViewContext<'a, 'w, V> {
|
||||
fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self {
|
||||
Self {
|
||||
window_cx: WindowContext::mutable(app, window),
|
||||
|
@ -1580,8 +1580,9 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
|||
f: impl FnOnce(WeakHandle<V>, AsyncWindowContext) -> Fut + Send + 'static,
|
||||
) -> Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
V: 'static + Send + Sync,
|
||||
R: 'static + Send,
|
||||
Fut: 'static + Future<Output = R> + Send,
|
||||
{
|
||||
let handle = self.handle();
|
||||
self.window_cx.spawn(move |_, cx| {
|
||||
|
@ -1640,11 +1641,8 @@ impl<'a, 'w, V: EventEmitter + Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'w, V> Context for ViewContext<'a, 'w, V>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
type EntityContext<'b, 'c, U: 'static + Send + Sync> = ViewContext<'b, 'c, U>;
|
||||
impl<'a, 'w, V> Context for ViewContext<'a, 'w, V> {
|
||||
type EntityContext<'b, 'c, U> = ViewContext<'b, 'c, U>;
|
||||
type Result<U> = U;
|
||||
|
||||
fn entity<T2: Send + Sync + 'static>(
|
||||
|
@ -1654,7 +1652,7 @@ where
|
|||
self.window_cx.entity(build_entity)
|
||||
}
|
||||
|
||||
fn update_entity<U: 'static + Send + Sync, R>(
|
||||
fn update_entity<U, R>(
|
||||
&mut self,
|
||||
handle: &Handle<U>,
|
||||
update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
|
||||
|
|
132
crates/gpui2_macros/src/derive_into_any_element.rs
Normal file
132
crates/gpui2_macros/src/derive_into_any_element.rs
Normal file
|
@ -0,0 +1,132 @@
|
|||
// impl<V> IntoAnyElement<V> for Modal
|
||||
// where
|
||||
// V: 'static + Send + Sync,
|
||||
// {
|
||||
// fn into_any(self) -> AnyElement<V> {
|
||||
// self.render().into_any()
|
||||
// }
|
||||
// }
|
||||
|
||||
// name the function pub fn derive_into_any_element
|
||||
|
||||
// Defining a derive macro
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{quote, format_ident};
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
pub fn derive_into_any_element(input: TokenStream) -> TokenStream {
|
||||
// Parse the input tokens into a syntax tree
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
let name = input.ident;
|
||||
let generics = input.generics;
|
||||
|
||||
// Check for the presence of a #[view_type = Foo] attribute on the struct
|
||||
let mut view_type = None;
|
||||
for attr in &input.attrs {
|
||||
if attr.path.is_ident("view_type") {
|
||||
if let Ok(meta) = attr.parse_meta() {
|
||||
if let syn::Meta::NameValue(nv) = meta {
|
||||
if let syn::Lit::Str(lit) = nv.lit {
|
||||
let view_type_token: proc_macro2::TokenStream =
|
||||
syn::parse_str(&lit.value()).unwrap();
|
||||
view_type = Some(view_type_token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let expanded = if let Some(view_type) = view_type {
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
quote! {
|
||||
impl #impl_generics gpui2::IntoAnyElement<#view_type> for #name #ty_generics
|
||||
#where_clause
|
||||
{
|
||||
fn into_any(self) -> gpui2::AnyElement<#view_type> {
|
||||
Self::render(self).into_any()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut trait_generics = generics.clone();
|
||||
trait_generics.params.push(syn::parse_quote! {
|
||||
ViewState: 'static + Send + Sync
|
||||
});
|
||||
|
||||
let (_, ty_generics, _) = generics.split_for_impl();
|
||||
let (impl_generics, _, where_clause) = trait_generics.split_for_impl();
|
||||
|
||||
let trampoline_name = format_ident!("{}{}", name, "Trampoline");
|
||||
|
||||
quote! {
|
||||
struct #trampoline_name<S, E> {
|
||||
contents: Option<E>,
|
||||
phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, E> #trampoline_name<S, E> {
|
||||
fn new(contents: E) -> Self {
|
||||
IntoAnyElementTrampolineName {
|
||||
contents: Some(contents),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, E> Element for #trampoline_name<S, E> {
|
||||
type ViewState = S;
|
||||
|
||||
type ElementState = AnyElement<S>;
|
||||
|
||||
fn id(&self) -> Option<crate::ElementId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn initialize(
|
||||
&mut self,
|
||||
view_state: &mut Self::ViewState,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> Self::ElementState {
|
||||
self.contents.take().unwrap().render(cx)
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> crate::LayoutId {
|
||||
element_state.layout(view_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: crate::Bounds<crate::Pixels>,
|
||||
view_state: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
element_state.paint(view_state, cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, E> IntoAnyElement<S> for IntoAnyElementTrampolineName<S, E> {
|
||||
fn into_any(self) -> AnyElement<S> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl #impl_generics gpui2::IntoAnyElement<ViewState> for #name #ty_generics
|
||||
#where_clause
|
||||
{
|
||||
fn into_any(self) -> gpui2::AnyElement<ViewState> {
|
||||
#trampoline_name::new(self).into_any()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
use proc_macro::TokenStream;
|
||||
|
||||
mod derive_element;
|
||||
mod derive_into_any_element;
|
||||
mod style_helpers;
|
||||
|
||||
#[proc_macro]
|
||||
|
@ -12,3 +13,8 @@ pub fn style_helpers(args: TokenStream) -> TokenStream {
|
|||
pub fn derive_element(input: TokenStream) -> TokenStream {
|
||||
derive_element::derive_element(input)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(IntoAnyElement, attributes(view_type))]
|
||||
pub fn derive_into_any_element(input: TokenStream) -> TokenStream {
|
||||
derive_into_any_element::derive_into_any_element(input)
|
||||
}
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use gpui2::{rems, AbsoluteLength};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{Icon, IconButton, Label, Panel, PanelSide};
|
||||
use gpui2::{div, rems, AbsoluteLength, IntoAnyElement};
|
||||
|
||||
#[derive(Element)]
|
||||
pub struct AssistantPanel<S: 'static + Send + Sync> {
|
||||
#[derive(IntoAnyElement)]
|
||||
pub struct AssistantPanel {
|
||||
id: ElementId,
|
||||
state_type: PhantomData<S>,
|
||||
current_side: PanelSide,
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> AssistantPanel<S> {
|
||||
impl AssistantPanel {
|
||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
state_type: PhantomData,
|
||||
current_side: PanelSide::default(),
|
||||
}
|
||||
}
|
||||
|
@ -26,54 +21,56 @@ impl<S: 'static + Send + Sync> AssistantPanel<S> {
|
|||
self
|
||||
}
|
||||
|
||||
fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
|
||||
let color = ThemeColor::new(cx);
|
||||
fn render<V>(mut self) -> impl IntoAnyElement<V> {
|
||||
div()
|
||||
|
||||
Panel::new(self.id.clone(), cx)
|
||||
.children(vec![div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.h_full()
|
||||
.px_2()
|
||||
.gap_2()
|
||||
// Header
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.justify_between()
|
||||
.gap_2()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.child(IconButton::new(Icon::Menu))
|
||||
.child(Label::new("New Conversation")),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_px()
|
||||
.child(IconButton::new(Icon::SplitMessage))
|
||||
.child(IconButton::new(Icon::Quote))
|
||||
.child(IconButton::new(Icon::MagicWand))
|
||||
.child(IconButton::new(Icon::Plus))
|
||||
.child(IconButton::new(Icon::Maximize)),
|
||||
),
|
||||
)
|
||||
// Chat Body
|
||||
.child(
|
||||
div()
|
||||
.id("chat-body")
|
||||
.w_full()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.overflow_y_scroll()
|
||||
.child(Label::new("Is this thing on?")),
|
||||
)
|
||||
.into_any()])
|
||||
.side(self.current_side)
|
||||
.width(AbsoluteLength::Rems(rems(32.)))
|
||||
// let color = ThemeColor::new(cx);
|
||||
|
||||
// Panel::new(self.id, cx)
|
||||
// .children(vec![div()
|
||||
// .flex()
|
||||
// .flex_col()
|
||||
// .h_full()
|
||||
// .px_2()
|
||||
// .gap_2()
|
||||
// // Header
|
||||
// .child(
|
||||
// div()
|
||||
// .flex()
|
||||
// .justify_between()
|
||||
// .gap_2()
|
||||
// .child(
|
||||
// div()
|
||||
// .flex()
|
||||
// .child(IconButton::new(Icon::Menu))
|
||||
// .child(Label::new("New Conversation")),
|
||||
// )
|
||||
// .child(
|
||||
// div()
|
||||
// .flex()
|
||||
// .items_center()
|
||||
// .gap_px()
|
||||
// .child(IconButton::new(Icon::SplitMessage))
|
||||
// .child(IconButton::new(Icon::Quote))
|
||||
// .child(IconButton::new(Icon::MagicWand))
|
||||
// .child(IconButton::new(Icon::Plus))
|
||||
// .child(IconButton::new(Icon::Maximize)),
|
||||
// ),
|
||||
// )
|
||||
// // Chat Body
|
||||
// .child(
|
||||
// div()
|
||||
// .id("chat-body")
|
||||
// .w_full()
|
||||
// .flex()
|
||||
// .flex_col()
|
||||
// .gap_3()
|
||||
// .overflow_y_scroll()
|
||||
// .child(Label::new("Is this thing on?")),
|
||||
// )
|
||||
// .into_any()])
|
||||
// .side(self.current_side)
|
||||
// .width(AbsoluteLength::Rems(rems(32.)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,29 +79,19 @@ pub use stories::*;
|
|||
|
||||
#[cfg(feature = "stories")]
|
||||
mod stories {
|
||||
use gpui2::AppContext;
|
||||
|
||||
use crate::Story;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Element)]
|
||||
pub struct AssistantPanelStory<S: 'static + Send + Sync> {
|
||||
state_type: PhantomData<S>,
|
||||
}
|
||||
#[derive(IntoAnyElement)]
|
||||
pub struct AssistantPanelStory;
|
||||
|
||||
impl<S: 'static + Send + Sync> AssistantPanelStory<S> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
state_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
_view: &mut S,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> impl Element<ViewState = S> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, AssistantPanel<S>>(cx))
|
||||
impl AssistantPanelStory {
|
||||
fn render<V>(self, cx: &mut ViewContext<V>) -> impl IntoAnyElement<V> {
|
||||
Story::container(self.0)
|
||||
.child(Story::title_for::<_, AssistantPanel>(self.0))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(AssistantPanel::new("assistant-panel"))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use gpui2::Div;
|
||||
use gpui2::{AppContext, Div};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{h_stack, HighlightedText};
|
||||
|
@ -9,33 +9,25 @@ use crate::{h_stack, HighlightedText};
|
|||
#[derive(Clone)]
|
||||
pub struct Symbol(pub Vec<HighlightedText>);
|
||||
|
||||
#[derive(Element)]
|
||||
pub struct Breadcrumb<S: 'static + Send + Sync> {
|
||||
state_type: PhantomData<S>,
|
||||
#[derive(IntoAnyElement)]
|
||||
pub struct Breadcrumb<'a> {
|
||||
path: PathBuf,
|
||||
symbols: Vec<Symbol>,
|
||||
cx: &'a AppContext,
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> Breadcrumb<S> {
|
||||
pub fn new(path: PathBuf, symbols: Vec<Symbol>) -> Self {
|
||||
Self {
|
||||
state_type: PhantomData,
|
||||
path,
|
||||
symbols,
|
||||
}
|
||||
impl<'a> Breadcrumb<'a> {
|
||||
pub fn new(path: PathBuf, symbols: Vec<Symbol>, cx: &'a AppContext) -> Self {
|
||||
Self { path, symbols, cx }
|
||||
}
|
||||
|
||||
fn render_separator(&self, cx: &WindowContext) -> Div<S> {
|
||||
fn render_separator<V>(&self, cx: &WindowContext) -> impl IntoAnyElement<V> {
|
||||
let color = ThemeColor::new(cx);
|
||||
div().child(" › ").text_color(color.text_muted)
|
||||
}
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
view_state: &mut S,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> impl Element<ViewState = S> {
|
||||
let color = ThemeColor::new(cx);
|
||||
fn render<V>(mut self) -> impl IntoAnyElement<V> {
|
||||
let color = ThemeColor::new(self.cx);
|
||||
|
||||
let symbols_len = self.symbols.len();
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ use chrono::NaiveDateTime;
|
|||
use crate::prelude::*;
|
||||
use crate::{Icon, IconButton, Input, Label, LabelColor};
|
||||
|
||||
#[derive(Element)]
|
||||
pub struct ChatPanel<S: 'static + Send + Sync> {
|
||||
#[derive(IntoAnyElement)]
|
||||
pub struct ChatPanel {
|
||||
element_id: ElementId,
|
||||
messages: Vec<ChatMessage<S>>,
|
||||
messages: Vec<ChatMessage>,
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> ChatPanel<S> {
|
||||
impl ChatPanel {
|
||||
pub fn new(element_id: impl Into<ElementId>) -> Self {
|
||||
Self {
|
||||
element_id: element_id.into(),
|
||||
|
@ -19,14 +19,14 @@ impl<S: 'static + Send + Sync> ChatPanel<S> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn messages(mut self, messages: Vec<ChatMessage<S>>) -> Self {
|
||||
pub fn messages(mut self, messages: Vec<ChatMessage>) -> Self {
|
||||
self.messages = messages;
|
||||
self
|
||||
}
|
||||
|
||||
fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
|
||||
fn render<S: 'static + Send + Sync>(self) -> impl IntoAnyElement<S> {
|
||||
div()
|
||||
.id(self.element_id.clone())
|
||||
.id(self.element_id)
|
||||
.flex()
|
||||
.flex_col()
|
||||
.justify_between()
|
||||
|
@ -62,7 +62,7 @@ impl<S: 'static + Send + Sync> ChatPanel<S> {
|
|||
.flex_col()
|
||||
.gap_3()
|
||||
.overflow_y_scroll()
|
||||
.children(self.messages.drain(..)),
|
||||
.children(self.messages),
|
||||
)
|
||||
// Composer
|
||||
.child(div().flex().my_2().child(Input::new("Message #design"))),
|
||||
|
@ -70,39 +70,30 @@ impl<S: 'static + Send + Sync> ChatPanel<S> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Element)]
|
||||
pub struct ChatMessage<S: 'static + Send + Sync> {
|
||||
state_type: PhantomData<S>,
|
||||
#[derive(IntoAnyElement)]
|
||||
pub struct ChatMessage {
|
||||
author: String,
|
||||
text: String,
|
||||
sent_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> ChatMessage<S> {
|
||||
impl ChatMessage {
|
||||
pub fn new(author: String, text: String, sent_at: NaiveDateTime) -> Self {
|
||||
Self {
|
||||
state_type: PhantomData,
|
||||
author,
|
||||
text,
|
||||
sent_at,
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
|
||||
fn render<S: 'static + Send + Sync>(mut self) -> impl Element<ViewState = S> {
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_2()
|
||||
.child(Label::new(self.author.clone()))
|
||||
.child(
|
||||
Label::new(self.sent_at.format("%m/%d/%Y").to_string())
|
||||
.color(LabelColor::Muted),
|
||||
),
|
||||
)
|
||||
.child(div().child(Label::new(self.text.clone())))
|
||||
.child(div().flex().gap_2().child(Label::new(self.author)).child(
|
||||
Label::new(self.sent_at.format("%m/%d/%Y").to_string()).color(LabelColor::Muted),
|
||||
))
|
||||
.child(div().child(Label::new(self.text)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,7 @@ impl Story {
|
|||
.bg(color.background)
|
||||
}
|
||||
|
||||
pub fn title<S: 'static + Send + Sync>(
|
||||
cx: &mut ViewContext<S>,
|
||||
title: &str,
|
||||
) -> impl Element<ViewState = S> {
|
||||
pub fn title<V>(cx: &mut ViewContext<V>, title: &str) -> impl Element<ViewState = V> {
|
||||
let color = ThemeColor::new(cx);
|
||||
|
||||
div()
|
||||
|
@ -30,16 +27,11 @@ impl Story {
|
|||
.child(title.to_owned())
|
||||
}
|
||||
|
||||
pub fn title_for<S: 'static + Send + Sync, T>(
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> impl Element<ViewState = S> {
|
||||
pub fn title_for<V, T>(cx: &mut ViewContext<V>) -> impl Element<ViewState = V> {
|
||||
Self::title(cx, std::any::type_name::<T>())
|
||||
}
|
||||
|
||||
pub fn label<S: 'static + Send + Sync>(
|
||||
cx: &mut ViewContext<S>,
|
||||
label: &str,
|
||||
) -> impl Element<ViewState = S> {
|
||||
pub fn label<V>(cx: &mut ViewContext<V>, label: &str) -> impl Element<ViewState = V> {
|
||||
let color = ThemeColor::new(cx);
|
||||
|
||||
div()
|
||||
|
|
|
@ -150,7 +150,7 @@ pub struct Themed<E> {
|
|||
|
||||
impl<E> IntoAnyElement<E::ViewState> for Themed<E>
|
||||
where
|
||||
E: Element,
|
||||
E: 'static + Element + Send + Sync,
|
||||
{
|
||||
fn into_any(self) -> AnyElement<E::ViewState> {
|
||||
AnyElement::new(self)
|
||||
|
@ -160,7 +160,10 @@ where
|
|||
#[derive(Default)]
|
||||
struct ThemeStack(Vec<Theme>);
|
||||
|
||||
impl<E: Element> Element for Themed<E> {
|
||||
impl<E> Element for Themed<E>
|
||||
where
|
||||
E: 'static + Element + Send + Sync,
|
||||
{
|
||||
type ViewState = E::ViewState;
|
||||
type ElementState = E::ElementState;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue