use pine_builtin_macro::BuiltinFunction;
use pine_core::{Color, DrawingOutput, PineOutput, PolylineObject};
use pine_interpreter::{Interpreter, RuntimeError, Value};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
#[derive(BuiltinFunction)]
#[builtin(name = "polyline.new")]
struct PolylineNew<O: PineOutput + DrawingOutput> {
points: Value<O>,
#[arg(default = false)]
curved: bool,
#[arg(default = false)]
closed: bool,
#[arg(default = "bar_index")]
xloc: String,
#[arg(default = None)]
line_color: Option<Color>,
#[arg(default = None)]
fill_color: Option<Color>,
#[arg(default = "solid")]
line_style: String,
#[arg(default = 1.0)]
line_width: f64,
}
impl<O: PineOutput + DrawingOutput> PolylineNew<O> {
fn execute(&self, ctx: &mut Interpreter<O>) -> Result<Value<O>, RuntimeError> {
let Value::Array(points) = &self.points else {
return Err(RuntimeError::TypeError(
"polyline.new: expected an array of points".into(),
));
};
let points: Vec<(f64, f64)> = points
.borrow()
.iter()
.map(crate::chart::point_coords)
.collect::<Result<_, _>>()?;
let id = ctx.output.add_polyline(PolylineObject {
points,
curved: self.curved,
closed: self.closed,
xloc: self.xloc.clone(),
line_color: self.line_color.clone(),
fill_color: self.fill_color.clone(),
line_style: self.line_style.clone(),
line_width: self.line_width,
});
Ok(Value::Number(id as f64))
}
}
#[derive(BuiltinFunction)]
#[builtin(name = "polyline.delete", output = DrawingOutput)]
struct PolylineDelete {
id: f64,
}
impl PolylineDelete {
fn execute<O: PineOutput + DrawingOutput>(
&self,
ctx: &mut Interpreter<O>,
) -> Result<Value<O>, RuntimeError> {
ctx.output.delete_polyline(self.id as usize);
Ok(Value::Na)
}
}
pub fn register<O: PineOutput + DrawingOutput>() -> Value<O> {
let mut members: HashMap<String, Value<O>> = HashMap::new();
members.insert("new".to_string(), PolylineNew::<O>::builtin_value());
members.insert("delete".to_string(), PolylineDelete::builtin_value::<O>());
members.insert(
"all".to_string(),
Value::Array(Rc::new(RefCell::new(Vec::new()))),
);
Value::Object {
type_name: "polyline".to_string(),
fields: Rc::new(RefCell::new(members)),
call: None,
value: None,
}
}