Output processing in the app layer is now done via commands. The script parsing takes place in a separate thread to prevent UI blocking. Output::Scalar was changed to a string. This value was always convereted to a string and rhai::Dynamic was not Send. Since the output is passed between threads now it was convereted to a string.
This commit is contained in:
parent
89a38c2220
commit
9cf41ad6ec
|
@ -583,7 +583,7 @@ mod tests {
|
|||
#[test]
|
||||
pub fn series_index() {
|
||||
let s = process(r#"series("ages", [18, 21, 25, 35]).sort(true)[1]"#).into_scalar();
|
||||
assert_eq!(s.cast::<i64>(), 25);
|
||||
assert_eq!(s, "25");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::dataframe;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -34,7 +36,7 @@ impl<'a> Engine<'a> {
|
|||
let series = rhai::Dynamic::cast::<dataframe::Series>(res);
|
||||
Output::Series(series)
|
||||
}
|
||||
Ok(res) => Output::Scalar(res),
|
||||
Ok(res) => Output::Scalar(res.to_string()),
|
||||
Err(e) => Output::Error(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +45,7 @@ impl<'a> Engine<'a> {
|
|||
#[derive(Debug, Clone)]
|
||||
pub enum Output {
|
||||
None,
|
||||
Scalar(rhai::Dynamic),
|
||||
Scalar(String),
|
||||
DataFrame(dataframe::DataFrame),
|
||||
Series(dataframe::Series),
|
||||
Error(String),
|
||||
|
@ -80,7 +82,7 @@ impl Output {
|
|||
}
|
||||
panic!("Not a series");
|
||||
}
|
||||
pub fn into_scalar(self) -> rhai::Dynamic {
|
||||
pub fn into_scalar(self) -> String {
|
||||
if let Self::Scalar(v) = self {
|
||||
return v;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use druid::AppDelegate;
|
||||
use abacus_core::Engine;
|
||||
use druid::{AppDelegate, Target};
|
||||
|
||||
use crate::{
|
||||
commands,
|
||||
|
@ -10,7 +11,7 @@ pub struct Delegate;
|
|||
impl AppDelegate<AppData> for Delegate {
|
||||
fn command(
|
||||
&mut self,
|
||||
_ctx: &mut druid::DelegateCtx,
|
||||
ctx: &mut druid::DelegateCtx,
|
||||
_target: druid::Target,
|
||||
cmd: &druid::Command,
|
||||
data: &mut AppData,
|
||||
|
@ -43,13 +44,59 @@ impl AppDelegate<AppData> for Delegate {
|
|||
}
|
||||
|
||||
if cmd.is(commands::PROCESS_WORKBOOK) {
|
||||
data.process();
|
||||
let scripts = data
|
||||
.blocks
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, b)| (idx, b.editor_data.content.to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let sink = ctx.get_external_handle();
|
||||
std::thread::spawn(move || {
|
||||
for (idx, script) in scripts.iter() {
|
||||
let mut engine = Engine::default();
|
||||
let output = engine.process_script(script);
|
||||
let _ = sink.submit_command(
|
||||
crate::commands::BLOCK_PROCESSED,
|
||||
(*idx, output),
|
||||
Target::Auto,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return druid::Handled::Yes;
|
||||
}
|
||||
|
||||
if cmd.is(commands::PROCESS_BLOCK) {
|
||||
if let Some(index) = cmd.get(commands::PROCESS_BLOCK) {
|
||||
data.process_block(*index);
|
||||
let index = *index;
|
||||
let script = data
|
||||
.blocks
|
||||
.get(index)
|
||||
.map(|b| b.editor_data.content.to_string());
|
||||
|
||||
if let Some(script) = script {
|
||||
let sink = ctx.get_external_handle();
|
||||
std::thread::spawn(move || {
|
||||
let mut engine = Engine::default();
|
||||
let output = engine.process_script(&script);
|
||||
let _ = sink.submit_command(
|
||||
crate::commands::BLOCK_PROCESSED,
|
||||
(index, output),
|
||||
Target::Auto,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return druid::Handled::Yes;
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.is(commands::BLOCK_PROCESSED) {
|
||||
if let Some((idx, output)) = cmd.get(commands::BLOCK_PROCESSED) {
|
||||
if let Some(block) = data.blocks.get_mut(*idx) {
|
||||
block.output = output.clone();
|
||||
}
|
||||
return druid::Handled::Yes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,9 @@ pub fn app_header_ui() -> impl Widget<AppData> {
|
|||
.with_child(
|
||||
Container::new(Padding::new(10.0, Svg::new(run_svg).fix_width(10.0)))
|
||||
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
|
||||
.on_click(|_ctx, data: &mut AppData, _env| data.process()),
|
||||
.on_click(|ctx, _data: &mut AppData, _env| {
|
||||
ctx.submit_command(crate::commands::PROCESS_WORKBOOK);
|
||||
}),
|
||||
)
|
||||
.with_spacer(20.0)
|
||||
.expand_width(),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use abacus_core::Output;
|
||||
use druid::Selector;
|
||||
|
||||
pub const PROCESS_WORKBOOK: Selector<()> = Selector::new("process-workbook");
|
||||
|
@ -7,3 +8,5 @@ pub const DELETE_BLOCK: Selector<usize> = Selector::new("delete-block");
|
|||
pub const RENAME_BLOCK: Selector<usize> = Selector::new("rename-block");
|
||||
|
||||
pub const CLOSE_MODAL: Selector<()> = Selector::new("close-modal");
|
||||
|
||||
pub const BLOCK_PROCESSED: Selector<(usize, Output)> = Selector::new("block-processed");
|
||||
|
|
|
@ -12,26 +12,18 @@ pub fn output_block() -> impl Widget<Block> {
|
|||
ViewSwitcher::new(
|
||||
|data: &Block, _env| data.clone(),
|
||||
|selector: &Block, _data, _env| match &selector.output {
|
||||
Output::Scalar(v) => {
|
||||
let str = match v {
|
||||
_ if v.is::<String>() => v.clone().cast::<String>(),
|
||||
_ if v.is::<&str>() => v.clone().cast::<&str>().to_string(),
|
||||
v => v.to_string(),
|
||||
};
|
||||
Box::new(Padding::new(
|
||||
25.0,
|
||||
Label::new(str)
|
||||
.with_font(
|
||||
FontDescriptor::new(FontFamily::MONOSPACE)
|
||||
.with_weight(FontWeight::BOLD),
|
||||
)
|
||||
.with_text_size(OUTPUT_FONT_SIZE)
|
||||
.padding(10.0)
|
||||
.background(Color::rgb8(30, 30, 30))
|
||||
.rounded(4.0)
|
||||
.expand_width(),
|
||||
))
|
||||
}
|
||||
Output::Scalar(str) => Box::new(Padding::new(
|
||||
25.0,
|
||||
Label::new(str.clone())
|
||||
.with_font(
|
||||
FontDescriptor::new(FontFamily::MONOSPACE).with_weight(FontWeight::BOLD),
|
||||
)
|
||||
.with_text_size(OUTPUT_FONT_SIZE)
|
||||
.padding(10.0)
|
||||
.background(Color::rgb8(30, 30, 30))
|
||||
.rounded(4.0)
|
||||
.expand_width(),
|
||||
)),
|
||||
Output::Error(e) => Box::new(Padding::new(
|
||||
25.0,
|
||||
Label::new(e.to_string())
|
||||
|
@ -87,7 +79,7 @@ pub fn output_block() -> impl Widget<Block> {
|
|||
.background(Color::rgb8(40, 40, 40)),
|
||||
);
|
||||
|
||||
for v in series.iter() {
|
||||
for v in series.iter().take(20) {
|
||||
col.add_child(
|
||||
Label::new(format_dataframe_value(v))
|
||||
.with_font(
|
||||
|
|
Loading…
Reference in New Issue