|
|
|
@ -13,185 +13,10 @@ use crate::{
|
|
|
|
|
ui::{Popup, Prompt, PromptEvent},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// TODO: Move the main configuration function to use this instead
|
|
|
|
|
pub fn helix_component_module() -> BuiltInModule {
|
|
|
|
|
let mut module = BuiltInModule::new("helix/components".to_string());
|
|
|
|
|
|
|
|
|
|
module.register_fn("new-component!", SteelDynamicComponent::new_dyn);
|
|
|
|
|
|
|
|
|
|
module.register_fn("SteelDynamicComponent?", |object: SteelVal| {
|
|
|
|
|
if let SteelVal::Custom(v) = object {
|
|
|
|
|
if let Some(wrapped) = v.borrow().as_any_ref().downcast_ref::<BoxDynComponent>() {
|
|
|
|
|
return wrapped.inner.as_any().is::<SteelDynamicComponent>();
|
|
|
|
|
} else {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"SteelDynamicComponent-state",
|
|
|
|
|
SteelDynamicComponent::get_state,
|
|
|
|
|
);
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"SteelDynamicComponent-render",
|
|
|
|
|
SteelDynamicComponent::get_render,
|
|
|
|
|
);
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"SteelDynamicComponent-handle-event",
|
|
|
|
|
SteelDynamicComponent::get_handle_event,
|
|
|
|
|
);
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"SteelDynamicComponent-should-update",
|
|
|
|
|
SteelDynamicComponent::should_update,
|
|
|
|
|
);
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"SteelDynamicComponent-cursor",
|
|
|
|
|
SteelDynamicComponent::cursor,
|
|
|
|
|
);
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"SteelDynamicComponent-required-size",
|
|
|
|
|
SteelDynamicComponent::get_required_size,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// engine.register_fn("WrappedComponent", WrappedDynComponent::new)
|
|
|
|
|
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"Popup::new",
|
|
|
|
|
|contents: &mut WrappedDynComponent,
|
|
|
|
|
position: helix_core::Position|
|
|
|
|
|
-> WrappedDynComponent {
|
|
|
|
|
let inner = contents.inner.take().unwrap(); // Panic, for now
|
|
|
|
|
|
|
|
|
|
WrappedDynComponent {
|
|
|
|
|
inner: Some(Box::new(
|
|
|
|
|
Popup::<BoxDynComponent>::new("popup", BoxDynComponent::new(inner))
|
|
|
|
|
.position(Some(position)),
|
|
|
|
|
)),
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// prompt: Cow<'static, str>,
|
|
|
|
|
// history_register: Option<char>,
|
|
|
|
|
// completion_fn: impl FnMut(&Editor, &str) -> Vec<Completion> + 'static,
|
|
|
|
|
// callback_fn: impl FnMut(&mut Context, &str, PromptEvent) + 'static,
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"Prompt::new",
|
|
|
|
|
|prompt: String, callback_fn: SteelVal| -> WrappedDynComponent {
|
|
|
|
|
let prompt = Prompt::new(
|
|
|
|
|
prompt.into(),
|
|
|
|
|
None,
|
|
|
|
|
|_, _| Vec::new(),
|
|
|
|
|
move |cx, input, prompt_event| {
|
|
|
|
|
if prompt_event != PromptEvent::Validate {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut ctx = Context {
|
|
|
|
|
register: None,
|
|
|
|
|
count: None,
|
|
|
|
|
editor: cx.editor,
|
|
|
|
|
callback: Vec::new(),
|
|
|
|
|
on_next_key_callback: None,
|
|
|
|
|
jobs: cx.jobs,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let cloned_func = callback_fn.clone();
|
|
|
|
|
// let thunk = move |engine: &mut Engine, cx, input| {
|
|
|
|
|
// engine.call_function_with_args(
|
|
|
|
|
// cloned_func,
|
|
|
|
|
// vec![cx, input],
|
|
|
|
|
|
|
|
|
|
// )
|
|
|
|
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
ENGINE
|
|
|
|
|
.with(|x| {
|
|
|
|
|
x.borrow_mut()
|
|
|
|
|
.with_mut_reference::<Context, Context>(&mut ctx)
|
|
|
|
|
.consume(move |engine, mut args| {
|
|
|
|
|
// Add the string as an argument to the callback
|
|
|
|
|
args.push(input.into_steelval().unwrap());
|
|
|
|
|
|
|
|
|
|
engine.call_function_with_args(cloned_func.clone(), args)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
WrappedDynComponent {
|
|
|
|
|
inner: Some(Box::new(prompt)),
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
module.register_fn("Picker::new", |values: Vec<String>| todo!());
|
|
|
|
|
|
|
|
|
|
// engine.register_fn(
|
|
|
|
|
// "Picker::new",
|
|
|
|
|
// |contents: &mut Wrapped
|
|
|
|
|
// )
|
|
|
|
|
|
|
|
|
|
module.register_fn("Component::Text", |contents: String| WrappedDynComponent {
|
|
|
|
|
inner: Some(Box::new(crate::ui::Text::new(contents))),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Separate this out into its own component module - This just lets us call the underlying
|
|
|
|
|
// component, not sure if we can go from trait object -> trait object easily but we'll see!
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"Component::render",
|
|
|
|
|
|t: &mut WrappedDynComponent,
|
|
|
|
|
area: helix_view::graphics::Rect,
|
|
|
|
|
frame: &mut tui::buffer::Buffer,
|
|
|
|
|
ctx: &mut Context| {
|
|
|
|
|
t.inner.as_mut().unwrap().render(
|
|
|
|
|
area,
|
|
|
|
|
frame,
|
|
|
|
|
&mut compositor::Context {
|
|
|
|
|
jobs: ctx.jobs,
|
|
|
|
|
editor: ctx.editor,
|
|
|
|
|
scroll: None,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"Component::handle-event",
|
|
|
|
|
|s: &mut WrappedDynComponent, event: &helix_view::input::Event, ctx: &mut Context| {
|
|
|
|
|
s.inner.as_mut().unwrap().handle_event(
|
|
|
|
|
event,
|
|
|
|
|
&mut compositor::Context {
|
|
|
|
|
jobs: ctx.jobs,
|
|
|
|
|
editor: ctx.editor,
|
|
|
|
|
scroll: None,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
module.register_fn("Component::should-update", |s: &mut WrappedDynComponent| {
|
|
|
|
|
s.inner.as_mut().unwrap().should_update()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"Component::cursor",
|
|
|
|
|
|s: &WrappedDynComponent, area: helix_view::graphics::Rect, ctx: &Editor| {
|
|
|
|
|
s.inner.as_ref().unwrap().cursor(area, ctx)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
module.register_fn(
|
|
|
|
|
"Component::required-size",
|
|
|
|
|
|s: &mut WrappedDynComponent, viewport: (u16, u16)| {
|
|
|
|
|
s.inner.as_mut().unwrap().required_size(viewport)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
module
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -242,6 +67,7 @@ impl SteelDynamicComponent {
|
|
|
|
|
) -> WrappedDynComponent {
|
|
|
|
|
let s = Self::new(name, state, render, h);
|
|
|
|
|
|
|
|
|
|
// TODO: Add guards here for the
|
|
|
|
|
WrappedDynComponent {
|
|
|
|
|
inner: Some(Box::new(s)),
|
|
|
|
|
}
|
|
|
|
|