aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/compositor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src/compositor.rs')
-rw-r--r--helix-term/src/compositor.rs86
1 files changed, 85 insertions, 1 deletions
diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs
index 4869032b..6e81cc81 100644
--- a/helix-term/src/compositor.rs
+++ b/helix-term/src/compositor.rs
@@ -34,7 +34,7 @@ pub struct Context<'a> {
pub callbacks: &'a mut LspCallbacks,
}
-pub trait Component {
+pub trait Component: Any + AnyComponent {
/// Process input events, return true if handled.
fn handle_event(&mut self, event: Event, ctx: &mut Context) -> EventResult {
EventResult::Ignored
@@ -60,6 +60,10 @@ pub trait Component {
// that way render can use it
None
}
+
+ fn type_name(&self) -> &'static str {
+ std::any::type_name::<Self>()
+ }
}
use anyhow::Error;
@@ -142,4 +146,84 @@ impl Compositor {
}
None
}
+
+ pub fn find(&mut self, type_name: &str) -> Option<&mut dyn Component> {
+ self.layers
+ .iter_mut()
+ .find(|component| component.type_name() == type_name)
+ .map(|component| component.as_mut())
+ }
+}
+
+// View casting, taken straight from Cursive
+
+use std::any::Any;
+
+/// A view that can be downcasted to its concrete type.
+///
+/// This trait is automatically implemented for any `T: Component`.
+pub trait AnyComponent {
+ /// Downcast self to a `Any`.
+ fn as_any(&self) -> &dyn Any;
+
+ /// Downcast self to a mutable `Any`.
+ fn as_any_mut(&mut self) -> &mut dyn Any;
+
+ /// Returns a boxed any from a boxed self.
+ ///
+ /// Can be used before `Box::downcast()`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use cursive_core::views::TextComponent;
+ /// # use cursive_core::view::Component;
+ /// let boxed: Box<Component> = Box::new(TextComponent::new("text"));
+ /// let text: Box<TextComponent> = boxed.as_boxed_any().downcast().unwrap();
+ /// ```
+ fn as_boxed_any(self: Box<Self>) -> Box<dyn Any>;
+}
+
+impl<T: Component> AnyComponent for T {
+ /// Downcast self to a `Any`.
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+
+ /// Downcast self to a mutable `Any`.
+ fn as_any_mut(&mut self) -> &mut dyn Any {
+ self
+ }
+
+ fn as_boxed_any(self: Box<Self>) -> Box<dyn Any> {
+ self
+ }
+}
+
+impl dyn AnyComponent {
+ /// Attempts to downcast `self` to a concrete type.
+ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
+ self.as_any().downcast_ref()
+ }
+
+ /// Attempts to downcast `self` to a concrete type.
+ pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
+ self.as_any_mut().downcast_mut()
+ }
+
+ /// Attempts to downcast `Box<Self>` to a concrete type.
+ pub fn downcast<T: Any>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
+ // Do the check here + unwrap, so the error
+ // value is `Self` and not `dyn Any`.
+ if self.as_any().is::<T>() {
+ Ok(self.as_boxed_any().downcast().unwrap())
+ } else {
+ Err(self)
+ }
+ }
+
+ /// Checks if this view is of type `T`.
+ pub fn is<T: Any>(&mut self) -> bool {
+ self.as_any().is::<T>()
+ }
}