1use std::collections::HashMap;
4
5#[derive(Clone, Debug, PartialEq)]
7pub struct Color {
8 pub r: u8, pub g: u8, pub b: u8, pub t: u8, }
13
14impl Color {
15 pub fn new(r: u8, g: u8, b: u8, t: u8) -> Self {
16 Color { r, g, b, t }
17 }
18}
19
20#[derive(Clone, Debug)]
22pub struct Label {
23 pub x: f64,
24 pub y: f64,
25 pub text: String,
26 pub xloc: String,
27 pub yloc: String,
28 pub color: Option<Color>,
29 pub style: String,
30 pub textcolor: Option<Color>,
31 pub size: String,
32 pub textalign: String,
33 pub tooltip: Option<String>,
34 pub text_font_family: String,
35}
36
37#[derive(Clone, Debug)]
40pub struct FillObject {
41 pub id1: Option<usize>,
43 pub id2: Option<usize>,
45 pub color: Option<Color>,
46 pub title: String,
47}
48
49#[derive(Clone, Debug, Default)]
51pub struct GlobalContext {
52 pub bgcolor: Option<Color>,
54 pub barcolor: Option<Color>,
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq)]
60pub enum Frequency {
61 All,
63 OncePerBar,
65 OncePerBarClose,
67}
68
69impl Frequency {
70 pub fn from_const(value: &str) -> Frequency {
72 match value {
73 "freq_all" => Frequency::All,
74 "freq_once_per_bar_close" => Frequency::OncePerBarClose,
75 _ => Frequency::OncePerBar,
76 }
77 }
78}
79
80#[derive(Clone, Debug, Default)]
84pub struct AlertCondition {
85 pub title: String,
86 pub message: String,
87 pub frequency: Option<Frequency>,
88}
89
90#[derive(Clone, Debug, Default)]
92pub struct Indicator {
93 pub title: String,
94 pub shorttitle: String,
95 pub overlay: bool,
96 pub format: String,
97 pub precision: Option<i64>,
98 pub timeframe: String,
99}
100
101#[derive(Clone, Debug, Default)]
103pub struct Library {
104 pub title: String,
105 pub overlay: bool,
106 pub dynamic_requests: Option<bool>,
107}
108
109#[derive(Clone, Debug)]
111pub struct LineObject {
112 pub x1: f64,
113 pub y1: f64,
114 pub x2: f64,
115 pub y2: f64,
116 pub xloc: String,
117 pub extend: String,
118 pub color: Option<Color>,
119 pub style: String,
120 pub width: f64,
121}
122
123#[derive(Clone, Debug, Default)]
125pub struct TableCell {
126 pub text: String,
127 pub text_color: Option<Color>,
128 pub bgcolor: Option<Color>,
129 pub text_size: String,
130 pub text_halign: String,
131 pub text_valign: String,
132}
133
134#[derive(Clone, Debug)]
136pub struct Table {
137 pub position: String,
138 pub columns: usize,
139 pub rows: usize,
140 pub bgcolor: Option<Color>,
141 pub cells: HashMap<(usize, usize), TableCell>,
142}
143
144#[derive(Clone, Debug)]
145pub struct PineBox {
146 pub left: f64,
147 pub top: f64,
148 pub right: f64,
149 pub bottom: f64,
150 pub border_color: Option<Color>,
151 pub border_width: f64,
152 pub border_style: String,
153 pub extend: String,
154 pub xloc: String,
155 pub bgcolor: Option<Color>,
156 pub text: String,
157 pub text_size: f64,
158 pub text_color: Option<Color>,
159 pub text_halign: String,
160 pub text_valign: String,
161 pub text_wrap: String,
162 pub text_font_family: String,
163}
164
165#[derive(Clone, Debug, Default)]
167pub struct Plot {
168 pub series: f64,
169 pub title: String,
170 pub color: Option<Color>,
171 pub linewidth: f64,
172 pub style: String,
173 pub trackprice: bool,
174 pub histbase: f64,
175 pub offset: f64,
176 pub join: bool,
177 pub editable: bool,
178 pub show_last: Option<f64>,
179 pub display: String,
180 pub format: Option<String>,
181 pub precision: Option<f64>,
182 pub force_overlay: bool,
183 pub linestyle: String,
184}
185
186#[derive(Clone, Debug)]
188pub struct Plotarrow {
189 pub series: f64,
190 pub title: String,
191 pub colorup: Option<Color>,
192 pub colordown: Option<Color>,
193 pub offset: f64,
194 pub minheight: f64,
195 pub maxheight: f64,
196 pub editable: bool,
197 pub show_last: Option<f64>,
198 pub display: String,
199 pub format: Option<String>,
200 pub precision: Option<f64>,
201 pub force_overlay: bool,
202}
203
204#[derive(Clone, Debug)]
206pub struct Plotbar {
207 pub open: f64,
208 pub high: f64,
209 pub low: f64,
210 pub close: f64,
211 pub title: String,
212 pub color: Option<Color>,
213 pub editable: bool,
214 pub show_last: Option<f64>,
215 pub display: String,
216 pub format: Option<String>,
217 pub precision: Option<f64>,
218 pub force_overlay: bool,
219}
220
221#[derive(Clone, Debug)]
223pub struct Plotcandle {
224 pub open: f64,
225 pub high: f64,
226 pub low: f64,
227 pub close: f64,
228 pub title: String,
229 pub color: Option<Color>,
230 pub wickcolor: Option<Color>,
231 pub editable: bool,
232 pub show_last: Option<f64>,
233 pub bordercolor: Option<Color>,
234 pub display: String,
235 pub format: Option<String>,
236 pub precision: Option<f64>,
237 pub force_overlay: bool,
238}
239
240#[derive(Clone, Debug)]
242pub struct Plotchar {
243 pub series: f64,
244 pub title: String,
245 pub char: String,
246 pub location: String,
247 pub color: Option<Color>,
248 pub offset: f64,
249 pub text: String,
250 pub textcolor: Option<Color>,
251 pub editable: bool,
252 pub size: String,
253 pub show_last: Option<f64>,
254 pub display: String,
255 pub format: Option<String>,
256 pub precision: Option<f64>,
257 pub force_overlay: bool,
258}
259
260#[derive(Clone, Debug)]
262pub struct Plotshape {
263 pub series: f64,
264 pub title: String,
265 pub style: String,
266 pub location: String,
267 pub color: Option<Color>,
268 pub offset: f64,
269 pub text: String,
270 pub textcolor: Option<Color>,
271 pub editable: bool,
272 pub size: String,
273 pub show_last: Option<f64>,
274 pub display: String,
275 pub format: Option<String>,
276 pub precision: Option<f64>,
277 pub force_overlay: bool,
278}
279
280#[derive(Debug, Clone, Copy, PartialEq, Eq)]
282pub enum LogLevel {
283 Info,
284 Warning,
285 Error,
286}
287
288#[derive(Debug, Clone)]
290pub struct LogEntry {
291 pub level: LogLevel,
292 pub message: String,
293}
294
295#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
301#[serde(untagged)]
302pub enum InputValue {
303 Bool(bool),
304 Int(i64),
305 Float(f64),
306 Str(String),
307 #[serde(skip)]
308 Color(Color),
309}
310
311#[derive(Debug, Clone)]
316pub struct Input {
317 pub kind: String,
320 pub title: String,
322 pub group: String,
324 pub default: InputValue,
326 pub value: InputValue,
327}
328
329pub trait PineOutput: Default + Clone + std::fmt::Debug + 'static {
334 fn clear(&mut self);
336}
337
338pub trait LogOutput: PineOutput {
340 fn add_log(&mut self, level: LogLevel, message: String);
342 fn get_logs(&self) -> &[LogEntry];
344}
345
346#[macro_export]
353macro_rules! impl_output_traits_delegate {
354 ($type:ty, $field:ident) => {
355 impl $crate::LogOutput for $type {
356 fn add_log(&mut self, level: $crate::LogLevel, message: String) {
357 self.$field.add_log(level, message)
358 }
359 fn get_logs(&self) -> &[$crate::LogEntry] {
360 self.$field.get_logs()
361 }
362 }
363
364 impl $crate::PlotOutput for $type {
365 fn add_plot(&mut self, plot: $crate::Plot) {
366 self.$field.add_plot(plot)
367 }
368 fn plots(&self) -> &[$crate::Plot] {
369 self.$field.plots()
370 }
371 fn add_plotarrow(&mut self, arrow: $crate::Plotarrow) {
372 self.$field.add_plotarrow(arrow)
373 }
374 fn plotarrows(&self) -> &[$crate::Plotarrow] {
375 self.$field.plotarrows()
376 }
377 fn add_plotbar(&mut self, bar: $crate::Plotbar) {
378 self.$field.add_plotbar(bar)
379 }
380 fn plotbars(&self) -> &[$crate::Plotbar] {
381 self.$field.plotbars()
382 }
383 fn add_plotcandle(&mut self, candle: $crate::Plotcandle) {
384 self.$field.add_plotcandle(candle)
385 }
386 fn plotcandles(&self) -> &[$crate::Plotcandle] {
387 self.$field.plotcandles()
388 }
389 fn add_plotchar(&mut self, char: $crate::Plotchar) {
390 self.$field.add_plotchar(char)
391 }
392 fn plotchars(&self) -> &[$crate::Plotchar] {
393 self.$field.plotchars()
394 }
395 fn add_plotshape(&mut self, shape: $crate::Plotshape) {
396 self.$field.add_plotshape(shape)
397 }
398 fn plotshapes(&self) -> &[$crate::Plotshape] {
399 self.$field.plotshapes()
400 }
401 }
402
403 impl $crate::LabelOutput for $type {
404 fn add_label(&mut self, label: $crate::Label) -> usize {
405 self.$field.add_label(label)
406 }
407 fn get_label(&self, id: usize) -> Option<&$crate::Label> {
408 self.$field.get_label(id)
409 }
410 fn get_label_mut(&mut self, id: usize) -> Option<&mut $crate::Label> {
411 self.$field.get_label_mut(id)
412 }
413 fn delete_label(&mut self, id: usize) -> bool {
414 self.$field.delete_label(id)
415 }
416 }
417
418 impl $crate::BoxOutput for $type {
419 fn add_box(&mut self, box_obj: $crate::PineBox) -> usize {
420 self.$field.add_box(box_obj)
421 }
422 fn get_box(&self, id: usize) -> Option<&$crate::PineBox> {
423 self.$field.get_box(id)
424 }
425 fn get_box_mut(&mut self, id: usize) -> Option<&mut $crate::PineBox> {
426 self.$field.get_box_mut(id)
427 }
428 fn delete_box(&mut self, id: usize) -> bool {
429 self.$field.delete_box(id)
430 }
431 }
432
433 impl $crate::InputOutput for $type {
434 fn add_input(&mut self, input: $crate::Input) {
435 self.$field.add_input(input)
436 }
437 fn inputs(&self) -> &[$crate::Input] {
438 self.$field.inputs()
439 }
440 }
441
442 impl $crate::MetadataOutput for $type {
443 fn set_indicator(&mut self, indicator: $crate::Indicator) {
444 self.$field.set_indicator(indicator)
445 }
446 fn indicator(&self) -> Option<&$crate::Indicator> {
447 self.$field.indicator()
448 }
449 fn set_library(&mut self, library: $crate::Library) {
450 self.$field.set_library(library)
451 }
452 fn library(&self) -> Option<&$crate::Library> {
453 self.$field.library()
454 }
455 }
456
457 impl $crate::AlertConditionOutput for $type {
458 fn add_alertcondition(&mut self, alert: $crate::AlertCondition) {
459 self.$field.add_alertcondition(alert)
460 }
461 fn alertconditions(&self) -> &[$crate::AlertCondition] {
462 self.$field.alertconditions()
463 }
464 }
465
466 impl $crate::FillOutput for $type {
467 fn add_fill(&mut self, fill: $crate::FillObject) {
468 self.$field.add_fill(fill)
469 }
470 fn fills(&self) -> &[$crate::FillObject] {
471 self.$field.fills()
472 }
473 }
474
475 impl $crate::GlobalOutput for $type {
476 fn set_bgcolor(&mut self, color: Option<$crate::Color>) {
477 self.$field.set_bgcolor(color)
478 }
479 fn set_barcolor(&mut self, color: Option<$crate::Color>) {
480 self.$field.set_barcolor(color)
481 }
482 fn global_context(&self) -> &$crate::GlobalContext {
483 self.$field.global_context()
484 }
485 }
486
487 impl $crate::LineOutput for $type {
488 fn add_line(&mut self, line: $crate::LineObject) -> usize {
489 self.$field.add_line(line)
490 }
491 fn get_line(&self, id: usize) -> Option<&$crate::LineObject> {
492 self.$field.get_line(id)
493 }
494 fn get_line_mut(&mut self, id: usize) -> Option<&mut $crate::LineObject> {
495 self.$field.get_line_mut(id)
496 }
497 fn delete_line(&mut self, id: usize) -> bool {
498 self.$field.delete_line(id)
499 }
500 }
501
502 impl $crate::DrawingOutput for $type {
503 fn add_linefill(&mut self, linefill: $crate::LinefillObject) -> usize {
504 self.$field.add_linefill(linefill)
505 }
506 fn get_linefill(&self, id: usize) -> Option<&$crate::LinefillObject> {
507 self.$field.get_linefill(id)
508 }
509 fn get_linefill_mut(&mut self, id: usize) -> Option<&mut $crate::LinefillObject> {
510 self.$field.get_linefill_mut(id)
511 }
512 fn delete_linefill(&mut self, id: usize) -> bool {
513 self.$field.delete_linefill(id)
514 }
515 fn add_polyline(&mut self, polyline: $crate::PolylineObject) -> usize {
516 self.$field.add_polyline(polyline)
517 }
518 fn delete_polyline(&mut self, id: usize) -> bool {
519 self.$field.delete_polyline(id)
520 }
521 }
522
523 impl $crate::TableOutput for $type {
524 fn add_table(&mut self, table: $crate::Table) -> usize {
525 self.$field.add_table(table)
526 }
527 fn get_table(&self, id: usize) -> Option<&$crate::Table> {
528 self.$field.get_table(id)
529 }
530 fn get_table_mut(&mut self, id: usize) -> Option<&mut $crate::Table> {
531 self.$field.get_table_mut(id)
532 }
533 fn delete_table(&mut self, id: usize) -> bool {
534 self.$field.delete_table(id)
535 }
536 }
537 };
538}
539
540pub trait PlotOutput: PineOutput {
542 fn add_plot(&mut self, plot: Plot);
544 fn plots(&self) -> &[Plot];
546
547 fn add_plotarrow(&mut self, arrow: Plotarrow);
549 fn plotarrows(&self) -> &[Plotarrow];
551
552 fn add_plotbar(&mut self, bar: Plotbar);
554 fn plotbars(&self) -> &[Plotbar];
556
557 fn add_plotcandle(&mut self, candle: Plotcandle);
559 fn plotcandles(&self) -> &[Plotcandle];
561
562 fn add_plotchar(&mut self, char: Plotchar);
564 fn plotchars(&self) -> &[Plotchar];
566
567 fn add_plotshape(&mut self, shape: Plotshape);
569 fn plotshapes(&self) -> &[Plotshape];
571}
572
573pub trait LabelOutput: PineOutput {
575 fn add_label(&mut self, label: Label) -> usize;
577 fn get_label(&self, id: usize) -> Option<&Label>;
579 fn get_label_mut(&mut self, id: usize) -> Option<&mut Label>;
581 fn delete_label(&mut self, id: usize) -> bool;
583}
584
585pub trait BoxOutput: PineOutput {
587 fn add_box(&mut self, box_obj: PineBox) -> usize;
589 fn get_box(&self, id: usize) -> Option<&PineBox>;
591 fn get_box_mut(&mut self, id: usize) -> Option<&mut PineBox>;
593 fn delete_box(&mut self, id: usize) -> bool;
595}
596
597pub trait TableOutput: PineOutput {
599 fn add_table(&mut self, table: Table) -> usize;
601 fn get_table(&self, id: usize) -> Option<&Table>;
603 fn get_table_mut(&mut self, id: usize) -> Option<&mut Table>;
605 fn delete_table(&mut self, id: usize) -> bool;
607}
608
609pub trait LineOutput: PineOutput {
611 fn add_line(&mut self, line: LineObject) -> usize;
613 fn get_line(&self, id: usize) -> Option<&LineObject>;
615 fn get_line_mut(&mut self, id: usize) -> Option<&mut LineObject>;
617 fn delete_line(&mut self, id: usize) -> bool;
619}
620
621#[derive(Clone, Debug)]
623pub struct LinefillObject {
624 pub line1: usize,
625 pub line2: usize,
626 pub color: Option<Color>,
627}
628
629#[derive(Clone, Debug, Default)]
631pub struct PolylineObject {
632 pub points: Vec<(f64, f64)>,
634 pub curved: bool,
635 pub closed: bool,
636 pub xloc: String,
637 pub line_color: Option<Color>,
638 pub fill_color: Option<Color>,
639 pub line_style: String,
640 pub line_width: f64,
641}
642
643pub trait DrawingOutput: PineOutput {
646 fn add_linefill(&mut self, linefill: LinefillObject) -> usize;
647 fn get_linefill(&self, id: usize) -> Option<&LinefillObject>;
648 fn get_linefill_mut(&mut self, id: usize) -> Option<&mut LinefillObject>;
649 fn delete_linefill(&mut self, id: usize) -> bool;
650 fn add_polyline(&mut self, polyline: PolylineObject) -> usize;
651 fn delete_polyline(&mut self, id: usize) -> bool;
652}
653
654pub trait FillOutput: PineOutput {
656 fn add_fill(&mut self, fill: FillObject);
657 fn fills(&self) -> &[FillObject];
658}
659
660pub trait GlobalOutput: PineOutput {
662 fn set_bgcolor(&mut self, color: Option<Color>);
663 fn set_barcolor(&mut self, color: Option<Color>);
664 fn global_context(&self) -> &GlobalContext;
666}
667
668pub trait AlertConditionOutput: PineOutput {
670 fn add_alertcondition(&mut self, alert: AlertCondition);
672 fn alertconditions(&self) -> &[AlertCondition];
674}
675
676pub trait MetadataOutput: PineOutput {
679 fn set_indicator(&mut self, indicator: Indicator);
681 fn indicator(&self) -> Option<&Indicator>;
683 fn set_library(&mut self, library: Library);
685 fn library(&self) -> Option<&Library>;
687}
688
689pub trait InputOutput: PineOutput {
691 fn add_input(&mut self, input: Input);
693 fn inputs(&self) -> &[Input];
695}
696
697#[derive(Default, Clone, Debug)]
699pub struct DefaultPineOutput {
700 labels: HashMap<usize, Label>,
702 next_label_id: usize,
704 boxes: HashMap<usize, PineBox>,
706 next_box_id: usize,
708 lines: HashMap<usize, LineObject>,
710 next_line_id: usize,
712 tables: HashMap<usize, Table>,
714 next_table_id: usize,
716 plots: Vec<Plot>,
718 plotarrows: Vec<Plotarrow>,
720 plotbars: Vec<Plotbar>,
722 plotcandles: Vec<Plotcandle>,
724 plotchars: Vec<Plotchar>,
726 plotshapes: Vec<Plotshape>,
728 logs: Vec<LogEntry>,
730 inputs: Vec<Input>,
732 indicator: Option<Indicator>,
734 library: Option<Library>,
736 globals: GlobalContext,
738 alertconditions: Vec<AlertCondition>,
740 fills: Vec<FillObject>,
742 linefills: HashMap<usize, LinefillObject>,
744 next_linefill_id: usize,
746 polylines: HashMap<usize, PolylineObject>,
748 next_polyline_id: usize,
750}
751
752impl PineOutput for DefaultPineOutput {
753 fn clear(&mut self) {
754 self.plots.clear();
757 self.plotarrows.clear();
758 self.plotbars.clear();
759 self.plotcandles.clear();
760 self.plotchars.clear();
761 self.plotshapes.clear();
762 self.logs.clear();
763 self.inputs.clear();
764 self.indicator = None;
765 self.globals = GlobalContext::default();
766 self.alertconditions.clear();
767 self.fills.clear();
768 }
774}
775
776impl LogOutput for DefaultPineOutput {
777 fn add_log(&mut self, level: LogLevel, message: String) {
778 self.logs.push(LogEntry { level, message });
779 }
780
781 fn get_logs(&self) -> &[LogEntry] {
782 &self.logs
783 }
784}
785
786impl PlotOutput for DefaultPineOutput {
787 fn add_plot(&mut self, plot: Plot) {
788 self.plots.push(plot);
789 }
790
791 fn plots(&self) -> &[Plot] {
792 &self.plots
793 }
794
795 fn add_plotarrow(&mut self, arrow: Plotarrow) {
796 self.plotarrows.push(arrow);
797 }
798
799 fn plotarrows(&self) -> &[Plotarrow] {
800 &self.plotarrows
801 }
802
803 fn add_plotbar(&mut self, bar: Plotbar) {
804 self.plotbars.push(bar);
805 }
806
807 fn plotbars(&self) -> &[Plotbar] {
808 &self.plotbars
809 }
810
811 fn add_plotcandle(&mut self, candle: Plotcandle) {
812 self.plotcandles.push(candle);
813 }
814
815 fn plotcandles(&self) -> &[Plotcandle] {
816 &self.plotcandles
817 }
818
819 fn add_plotchar(&mut self, char: Plotchar) {
820 self.plotchars.push(char);
821 }
822
823 fn plotchars(&self) -> &[Plotchar] {
824 &self.plotchars
825 }
826
827 fn add_plotshape(&mut self, shape: Plotshape) {
828 self.plotshapes.push(shape);
829 }
830
831 fn plotshapes(&self) -> &[Plotshape] {
832 &self.plotshapes
833 }
834}
835
836impl LabelOutput for DefaultPineOutput {
837 fn add_label(&mut self, label: Label) -> usize {
838 let id = self.next_label_id;
839 self.next_label_id += 1;
840 self.labels.insert(id, label);
841 id
842 }
843
844 fn get_label(&self, id: usize) -> Option<&Label> {
845 self.labels.get(&id)
846 }
847
848 fn get_label_mut(&mut self, id: usize) -> Option<&mut Label> {
849 self.labels.get_mut(&id)
850 }
851
852 fn delete_label(&mut self, id: usize) -> bool {
853 self.labels.remove(&id).is_some()
854 }
855}
856
857impl BoxOutput for DefaultPineOutput {
858 fn add_box(&mut self, box_obj: PineBox) -> usize {
859 let id = self.next_box_id;
860 self.next_box_id += 1;
861 self.boxes.insert(id, box_obj);
862 id
863 }
864
865 fn get_box(&self, id: usize) -> Option<&PineBox> {
866 self.boxes.get(&id)
867 }
868
869 fn get_box_mut(&mut self, id: usize) -> Option<&mut PineBox> {
870 self.boxes.get_mut(&id)
871 }
872
873 fn delete_box(&mut self, id: usize) -> bool {
874 self.boxes.remove(&id).is_some()
875 }
876}
877
878impl LineOutput for DefaultPineOutput {
879 fn add_line(&mut self, line: LineObject) -> usize {
880 let id = self.next_line_id;
881 self.next_line_id += 1;
882 self.lines.insert(id, line);
883 id
884 }
885
886 fn get_line(&self, id: usize) -> Option<&LineObject> {
887 self.lines.get(&id)
888 }
889
890 fn get_line_mut(&mut self, id: usize) -> Option<&mut LineObject> {
891 self.lines.get_mut(&id)
892 }
893
894 fn delete_line(&mut self, id: usize) -> bool {
895 self.lines.remove(&id).is_some()
896 }
897}
898
899impl DrawingOutput for DefaultPineOutput {
900 fn add_linefill(&mut self, linefill: LinefillObject) -> usize {
901 let id = self.next_linefill_id;
902 self.next_linefill_id += 1;
903 self.linefills.insert(id, linefill);
904 id
905 }
906
907 fn get_linefill(&self, id: usize) -> Option<&LinefillObject> {
908 self.linefills.get(&id)
909 }
910
911 fn get_linefill_mut(&mut self, id: usize) -> Option<&mut LinefillObject> {
912 self.linefills.get_mut(&id)
913 }
914
915 fn delete_linefill(&mut self, id: usize) -> bool {
916 self.linefills.remove(&id).is_some()
917 }
918
919 fn add_polyline(&mut self, polyline: PolylineObject) -> usize {
920 let id = self.next_polyline_id;
921 self.next_polyline_id += 1;
922 self.polylines.insert(id, polyline);
923 id
924 }
925
926 fn delete_polyline(&mut self, id: usize) -> bool {
927 self.polylines.remove(&id).is_some()
928 }
929}
930
931impl TableOutput for DefaultPineOutput {
932 fn add_table(&mut self, table: Table) -> usize {
933 let id = self.next_table_id;
934 self.next_table_id += 1;
935 self.tables.insert(id, table);
936 id
937 }
938
939 fn get_table(&self, id: usize) -> Option<&Table> {
940 self.tables.get(&id)
941 }
942
943 fn get_table_mut(&mut self, id: usize) -> Option<&mut Table> {
944 self.tables.get_mut(&id)
945 }
946
947 fn delete_table(&mut self, id: usize) -> bool {
948 self.tables.remove(&id).is_some()
949 }
950}
951
952impl InputOutput for DefaultPineOutput {
953 fn add_input(&mut self, input: Input) {
954 self.inputs.push(input);
955 }
956
957 fn inputs(&self) -> &[Input] {
958 &self.inputs
959 }
960}
961
962impl MetadataOutput for DefaultPineOutput {
963 fn set_indicator(&mut self, indicator: Indicator) {
964 self.indicator = Some(indicator);
965 }
966
967 fn indicator(&self) -> Option<&Indicator> {
968 self.indicator.as_ref()
969 }
970
971 fn set_library(&mut self, library: Library) {
972 self.library = Some(library);
973 }
974
975 fn library(&self) -> Option<&Library> {
976 self.library.as_ref()
977 }
978}
979
980impl AlertConditionOutput for DefaultPineOutput {
981 fn add_alertcondition(&mut self, alert: AlertCondition) {
982 self.alertconditions.push(alert);
983 }
984
985 fn alertconditions(&self) -> &[AlertCondition] {
986 &self.alertconditions
987 }
988}
989
990impl FillOutput for DefaultPineOutput {
991 fn add_fill(&mut self, fill: FillObject) {
992 self.fills.push(fill);
993 }
994
995 fn fills(&self) -> &[FillObject] {
996 &self.fills
997 }
998}
999
1000impl GlobalOutput for DefaultPineOutput {
1001 fn set_bgcolor(&mut self, color: Option<Color>) {
1002 self.globals.bgcolor = color;
1003 }
1004
1005 fn set_barcolor(&mut self, color: Option<Color>) {
1006 self.globals.barcolor = color;
1007 }
1008
1009 fn global_context(&self) -> &GlobalContext {
1010 &self.globals
1011 }
1012}