use abacus_core::Output; use druid::{ widget::{Container, Flex, Label, Padding, Scroll, ViewSwitcher}, Color, FontDescriptor, FontFamily, FontWeight, Widget, WidgetExt, }; use crate::data::Block; const OUTPUT_FONT_SIZE: f64 = 16.0; pub fn output_block() -> impl Widget { ViewSwitcher::new( |data: &Block, _env| data.clone(), |selector: &Block, _data, _env| match &selector.output { Output::Scalar(v) => { let str = match v { _ if v.is::() => v.clone().cast::(), _ 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::Error(e) => Box::new(Padding::new( 25.0, Label::new(e.to_string()) .with_font( FontDescriptor::new(FontFamily::MONOSPACE).with_weight(FontWeight::BOLD), ) .with_text_alignment(druid::TextAlignment::Center) .with_line_break_mode(druid::widget::LineBreaking::WordWrap) .with_text_size(OUTPUT_FONT_SIZE) .padding(10.0) .background(Color::rgb8(30, 10, 10)) .expand_width(), )), Output::Series(series) => { let mut flex = Flex::row(); for v in series.iter() { flex.add_child( Label::new(v.to_string()) .with_font( FontDescriptor::new(FontFamily::MONOSPACE) .with_weight(FontWeight::BOLD), ) .with_text_size(OUTPUT_FONT_SIZE) .padding(3.0) .border(Color::rgb8(60, 60, 60), 1.0), ); } Box::new(Padding::new( 25.0, flex.padding(10.0) .background(Color::rgb8(30, 30, 30)) .rounded(4.0) .expand_width(), )) } Output::DataFrame(frame) => { let mut flex = Flex::row(); for series in frame.iter() { let mut col = Flex::column() .cross_axis_alignment(druid::widget::CrossAxisAlignment::Fill); col.add_child( Label::new(series.name()) .with_font( FontDescriptor::new(FontFamily::MONOSPACE) .with_weight(FontWeight::BLACK), ) .with_text_size(OUTPUT_FONT_SIZE) .with_text_color(Color::rgb8(150, 150, 150)) .padding(3.0) .border(Color::rgb8(50, 50, 50), 1.0) .background(Color::rgb8(40, 40, 40)), ); for v in series.iter() { col.add_child( Label::new(format_dataframe_value(v)) .with_font( FontDescriptor::new(FontFamily::MONOSPACE) .with_weight(FontWeight::MEDIUM), ) .with_text_size(OUTPUT_FONT_SIZE) .padding(3.0) .border(Color::rgb8(50, 50, 50), 1.0), ); } flex.add_child(col); } Box::new(Padding::new( 25.0, Container::new( Scroll::new(flex.background(Color::rgb8(30, 30, 30)).expand_width()) .horizontal() .expand_width(), ) .rounded(4.0) .border(Color::rgb8(30, 30, 30), 5.0) .background(Color::rgb8(30, 30, 30)) .expand_width(), )) } Output::None => Box::new(Container::new(Label::new(""))), }, ) } fn format_dataframe_value(value: abacus_core::AnyValue) -> String { match value { abacus_core::AnyValue::Utf8(v) => v.to_string(), abacus_core::AnyValue::Utf8Owned(v) => v, _ => value.to_string(), } }