1use self::DataSourceType::*;
6
7pub use self::LabelType::*;
8pub use self::PlotType::*;
9use crate::coordinates::*;
10
11use crate::datatype::*;
12use crate::options::*;
13use crate::util::{escape, OneWayOwned};
14use crate::writer::*;
15use crate::ColorType;
16use std::borrow::Borrow;
17use std::fs;
18use std::path;
19
20pub struct PlotElement
21{
22 data: Vec<f64>,
23 num_rows: usize,
24 num_cols: usize,
25 plot_type: PlotType,
26 source_type: DataSourceType,
27 is_3d: bool,
28 options: Vec<PlotOption<String>>,
29}
30
31impl PlotElement
32{
33 pub fn new_plot(
34 plot_type: PlotType, data: Vec<f64>, num_rows: usize, num_cols: usize,
35 options: &[PlotOption<&str>],
36 ) -> PlotElement
37 {
38 PlotElement {
39 data,
40 num_rows,
41 num_cols,
42 plot_type,
43 source_type: Record,
44 is_3d: false,
45 options: options.to_one_way_owned(),
46 }
47 }
48
49 pub fn new_plot_matrix<T: DataType, X: IntoIterator<Item = T>>(
50 plot_type: PlotType, is_3d: bool, mat: X, num_rows: usize, num_cols: usize,
51 dimensions: Option<(f64, f64, f64, f64)>, options: Vec<PlotOption<String>>,
52 ) -> PlotElement
53 {
54 let mut count = 0;
55 let mut data = vec![];
56 for x in mat
58 {
59 data.push(x.get());
60 count += 1;
61 }
62
63 if count < num_rows * num_cols
64 {
65 data.resize(num_rows * num_cols, f64::NAN);
66 }
67
68 let source_type = match dimensions
69 {
70 Some((x1, y1, x2, y2)) => SizedArray(x1, y1, x2, y2),
71 None => Array,
72 };
73
74 PlotElement {
75 data,
76 num_rows,
77 num_cols,
78 plot_type,
79 source_type,
80 is_3d,
81 options,
82 }
83 }
84
85 fn write_args(&self, source: &str, writer: &mut dyn Writer, version: GnuplotVersion)
86 {
87 let options = &self.options;
88 match self.source_type
89 {
90 Record =>
91 {
92 write!(
93 writer,
94 r#" "{}" binary endian=little record={} format="%float64" using "#,
95 source, self.num_rows
96 );
97
98 let mut col_idx = 1;
99 while col_idx < self.num_cols + 1
100 {
101 write!(writer, "{}", col_idx);
102 if col_idx < self.num_cols
103 {
104 writer.write_str(":");
105 }
106 col_idx += 1;
107 }
108 }
109 _ =>
110 {
111 write!(
112 writer,
113 r#" "{}" binary endian=little array=({},{}) format="%float64" "#,
114 source, self.num_cols, self.num_rows
115 );
116
117 if let SizedArray(x1, y1, x2, y2) = self.source_type
118 {
119 let (x1, x2) = if x1 > x2 { (x2, x1) } else { (x1, x2) };
120
121 let (y1, y2) = if y1 > y2 { (y2, y1) } else { (y1, y2) };
122 write!(writer, "origin=({:.12e},{:.12e}", x1, y1);
123 if self.is_3d
124 {
125 write!(writer, ",0");
126 }
127 write!(writer, ") ");
128 if self.num_cols > 1
129 {
130 write!(
131 writer,
132 "dx={:.12e} ",
133 (x2 - x1) / (self.num_cols as f64 - 1.0)
134 );
135 }
136 else
137 {
138 write!(writer, "dx=1 ");
139 }
140 if self.num_rows > 1
141 {
142 write!(
143 writer,
144 "dy={:.12e} ",
145 (y2 - y1) / (self.num_rows as f64 - 1.0)
146 );
147 }
148 else
149 {
150 write!(writer, "dy=1 ");
151 }
152 }
153 }
154 }
155
156 writer.write_str(" with ");
157 let type_str = match self.plot_type
158 {
159 Lines => "lines",
160 Points => "points",
161 LinesPoints => "linespoints",
162 XErrorLines => "xerrorlines",
163 YErrorLines => "yerrorlines",
164 XErrorBars => "xerrorbars",
165 YErrorBars => "yerrorbars",
166 XYErrorBars => "xyerrorbars",
167 FillBetween => "filledcurves",
168 Polygons => "polygons",
169 Boxes => "boxes",
170 BoxAndWhisker => "candlestick",
171 BoxXYError => "boxxyerror",
172 BoxErrorBars => "boxerrorbars",
173 Pm3D => "pm3d",
174 Image => "image",
175 };
176 writer.write_str(type_str);
177
178 if self.plot_type.is_fill()
179 {
180 if let FillBetween = self.plot_type
181 {
182 first_opt! {options,
183 FillRegion(d) =>
184 {
185 match d
186 {
187 Above => {writer.write_str(" above");},
188 Below => {writer.write_str(" below");},
189 Between => (), }
191 }
192 }
193 }
194
195 writer.write_str(" fill ");
196
197 let mut is_pattern = false;
198 first_opt! {self.options,
199 FillPattern(pattern_opt) =>
200 {
201 is_pattern = true;
202 writer.write_str("pattern ");
203 if let Fix(val) = pattern_opt
204 {
205 write!(writer, "{}", val as i32);
206 }
207 }
208 }
209
210 if !is_pattern
211 {
212 let mut color_has_alpha = false;
213 first_opt! {self.options,
214 Color(ref c) => {
215 color_has_alpha = c.has_alpha()
216 }
217 }
218 if !color_has_alpha
219 {
220 writer.write_str("transparent ");
221 }
222 writer.write_str("solid");
223 let mut alpha = 1.;
224 first_opt! {self.options,
225 FillAlpha(a) =>
226 {
227 alpha = a;
228 }
229 }
230 write!(writer, " {:.12e}", alpha);
231 }
232
233 if self.plot_type.is_line()
234 {
235 writer.write_str(" border ");
237 first_opt! {self.options,
238 BorderColor(ref s) =>
239 {
240 writer.write_str(&s.command());
241 }
242 }
243 }
244 else
245 {
246 writer.write_str(" noborder");
247 }
248 }
249
250 if self.plot_type.is_line()
251 {
252 AxesCommonData::write_line_options(writer, options, version);
253 }
254
255 if self.plot_type.is_points()
256 {
257 first_opt! {self.options,
258 PointSymbol(s) =>
259 {
260 write!(writer, " pt {}", char_to_symbol(s));
261 }
262 }
263
264 first_opt! {self.options,
265 PointSize(z) =>
266 {
267 write!(writer, " ps {}", z);
268 }
269 }
270 }
271
272 AxesCommonData::write_color_options(writer, &self.options, self.plot_type.is_fill(), None);
273
274 writer.write_str(" t \"");
275 first_opt! {self.options,
276 Caption(ref s) =>
277 {
278 writer.write_str(&escape(s));
279 }
280 }
281 writer.write_str("\"");
282
283 first_opt! {self.options,
284 WhiskerBars(f) =>
285 {
286 write!(writer, " whiskerbars {}", f);
287 }
288 }
289
290 first_opt! {self.options,
291 Axes(x, y) =>
292 {
293 write!(writer, " axes {}{}",
294 match x
295 {
296 XAxis::X1 => "x1",
297 XAxis::X2 => "x2",
298 },
299 match y
300 {
301 YAxis::Y1 => "y1",
302 YAxis::Y2 => "y2",
303 }
304 );
305 }
306 }
307 }
308
309 fn write_data(&self, writer: &mut dyn Writer)
310 {
311 for d in &self.data
312 {
313 writer.write_le_f64(*d);
314 }
315 }
316}
317
318pub struct LabelData
319{
320 pub label_type: LabelType,
321 pub text: String,
322 pub options: Vec<LabelOption<String>>,
323}
324
325impl LabelData
326{
327 fn new(label_type: LabelType) -> Self
328 {
329 Self {
330 label_type,
331 text: "".into(),
332 options: vec![],
333 }
334 }
335
336 pub fn set(&mut self, text: String, options: Vec<LabelOption<String>>)
337 {
338 self.text = text;
339 self.options = options;
340 }
341
342 pub fn write_out_commands(&self, writer: &mut dyn Writer)
343 {
344 let w = writer;
345 w.write_str("set ");
346
347 self.label_type.write_label_str(w);
348
349 w.write_str(" \"");
350 w.write_str(&escape(&self.text));
351 w.write_str("\"");
352
353 write_out_label_options(self.label_type, &self.options[..], w);
354
355 w.write_str("\n");
356 }
357
358 pub fn reset_state(&self, writer: &mut dyn Writer)
359 {
360 if let Label(tag, ..) = self.label_type
361 {
362 writeln!(writer, "unset label {}", tag);
363 }
364 }
365}
366
367#[derive(Copy, Clone)]
368pub enum LabelType
369{
370 XLabel,
371 YLabel,
372 X2Label,
373 Y2Label,
374 ZLabel,
375 CBLabel,
376 TitleLabel,
377 Label(i32, Coordinate, Coordinate),
378 AxesTicks,
379}
380
381impl LabelType
382{
383 fn is_label(&self) -> bool
384 {
385 matches!(*self, Label(..))
386 }
387
388 fn write_label_str(&self, w: &mut dyn Writer)
389 {
390 match *self
391 {
392 XLabel =>
393 {
394 w.write_str("xlabel");
395 }
396 YLabel =>
397 {
398 w.write_str("ylabel");
399 }
400 X2Label =>
401 {
402 w.write_str("x2label");
403 }
404 Y2Label =>
405 {
406 w.write_str("y2label");
407 }
408 ZLabel =>
409 {
410 w.write_str("zlabel");
411 }
412 CBLabel =>
413 {
414 w.write_str("cblabel");
415 }
416 TitleLabel =>
417 {
418 w.write_str("title");
419 }
420 Label(tag, ..) =>
421 {
422 write!(w, "label {}", tag);
423 }
424 _ => panic!("Invalid label type"),
425 }
426 }
427
428 fn from_axis(axis_type: TickAxis) -> Self
429 {
430 match axis_type
431 {
432 TickAxis::X => XLabel,
433 TickAxis::Y => YLabel,
434 TickAxis::X2 => X2Label,
435 TickAxis::Y2 => Y2Label,
436 TickAxis::Z => ZLabel,
437 TickAxis::CB => CBLabel,
438 }
439 }
440}
441
442pub fn write_out_label_options(
443 label_type: LabelType, options: &[LabelOption<String>], writer: &mut dyn Writer,
444)
445{
446 let w = writer;
447 if let Label(_, x, y) = label_type
448 {
449 write!(w, " at {},{} front", x, y);
450 }
451
452 first_opt! {options,
453 TextOffset(x, y) =>
454 {
455 write!(w, " offset character {:.12e},{:.12e}", x, y);
456 }
457 }
458
459 first_opt! {options,
460 TextColor(ref s) =>
461 {
462 write!(w, r#" tc {}"#, s.command());
463 }
464 }
465
466 first_opt! {options,
467 Font(ref f, s) =>
468 {
469 write!(w, r#" font "{},{}""#, f, s);
470 }
471 }
472
473 first_opt! {options,
474 Rotate(a) =>
475 {
476 write!(w, " rotate by {:.12e}", a);
477 }
478 }
479
480 if label_type.is_label()
481 {
482 let mut have_point = false;
483 first_opt! {options,
484 MarkerSymbol(s) =>
485 {
486 write!(w, " point pt {}", char_to_symbol(s));
487 have_point = true;
488 }
489 }
490
491 if have_point
492 {
493 first_opt! {options,
494 MarkerColor(ref s) =>
495 {
496 write!(w, r#" lc {}"#, s.command());
497 }
498 }
499
500 first_opt! {options,
501 MarkerSize(z) =>
502 {
503 write!(w, " ps {:.12e}", z);
504 }
505 }
506 }
507
508 first_opt! {options,
509 TextAlign(a) =>
510 {
511 write!(w, "{}", match a
512 {
513 AlignLeft => " left",
514 AlignRight => " right",
515 _ => " center",
516 });
517 }
518 }
519 }
520}
521
522#[derive(Copy, Clone, PartialEq)]
523pub enum TickAxis
524{
525 X,
526 Y,
527 X2,
528 Y2,
529 Z,
530 CB,
531}
532
533impl TickAxis
534{
535 pub fn get_axis_str(&self) -> &str
536 {
537 match *self
538 {
539 TickAxis::X => "x",
540 TickAxis::Y => "y",
541 TickAxis::X2 => "x2",
542 TickAxis::Y2 => "y2",
543 TickAxis::Z => "z",
544 TickAxis::CB => "cb",
545 }
546 }
547
548 pub fn get_tick_str(&self) -> &str
549 {
550 match *self
551 {
552 TickAxis::X => "xtics",
553 TickAxis::Y => "ytics",
554 TickAxis::X2 => "x2tics",
555 TickAxis::Y2 => "y2tics",
556 TickAxis::Z => "ztics",
557 TickAxis::CB => "cbtics",
558 }
559 }
560
561 pub fn get_mtick_str(&self) -> &str
562 {
563 match *self
564 {
565 TickAxis::X => "mxtics",
566 TickAxis::Y => "mytics",
567 TickAxis::X2 => "mx2tics",
568 TickAxis::Y2 => "my2tics",
569 TickAxis::Z => "mztics",
570 TickAxis::CB => "mcbtics",
571 }
572 }
573
574 pub fn get_range_str(&self) -> &str
575 {
576 match *self
577 {
578 TickAxis::X => "xrange",
579 TickAxis::Y => "yrange",
580 TickAxis::X2 => "x2range",
581 TickAxis::Y2 => "y2range",
582 TickAxis::Z => "zrange",
583 TickAxis::CB => "cbrange",
584 }
585 }
586}
587
588pub enum PlotType
589{
590 Lines,
591 Points,
592 LinesPoints,
593 XErrorLines,
594 YErrorLines,
595 XErrorBars,
596 XYErrorBars,
597 YErrorBars,
598 FillBetween,
599 Polygons,
600 Boxes,
601 BoxErrorBars,
602 BoxAndWhisker,
603 BoxXYError,
604 Pm3D,
605 Image,
606}
607
608impl PlotType
609{
610 fn is_line(&self) -> bool
611 {
612 matches!(
613 *self,
614 Lines
615 | LinesPoints
616 | XErrorLines
617 | Boxes | YErrorLines
618 | BoxAndWhisker
619 | BoxXYError | BoxErrorBars
620 | Polygons
621 )
622 }
623
624 fn is_points(&self) -> bool
625 {
626 matches!(
627 *self,
628 Points
629 | LinesPoints
630 | XErrorLines
631 | YErrorLines
632 | XErrorBars | YErrorBars
633 | XYErrorBars
634 )
635 }
636
637 fn is_fill(&self) -> bool
638 {
639 matches!(
640 *self,
641 Boxes | FillBetween | BoxAndWhisker | BoxXYError | BoxErrorBars | Polygons
642 )
643 }
644}
645
646pub enum TickType
647{
648 None,
649 Custom(Vec<Tick<f64, String>>),
650 Auto(AutoOption<f64>, u32),
651}
652
653pub struct AxisData
654{
655 pub tick_options: Vec<TickOption<String>>,
656 pub label_options: Vec<LabelOption<String>>,
657 pub tick_type: TickType,
658 pub log_base: Option<f64>,
659 pub axis: TickAxis,
660 pub min: AutoOption<f64>,
661 pub max: AutoOption<f64>,
662 pub reverse: bool,
663 pub grid: bool,
664 pub mgrid: bool,
665 pub is_time: bool,
666 pub show: bool,
667 pub label: LabelData,
668 pub options: Vec<PlotOption<String>>,
669}
670
671impl AxisData
672{
673 pub fn new(axis: TickAxis) -> Self
674 {
675 AxisData {
676 tick_options: vec![],
677 label_options: vec![],
678 tick_type: TickType::Auto(Auto, 0),
679 log_base: None,
680 axis,
681 min: Auto,
682 max: Auto,
683 reverse: false,
684 grid: false,
685 mgrid: false,
686 is_time: false,
687 show: false,
688 label: LabelData::new(LabelType::from_axis(axis)),
689 options: vec![],
690 }
691 }
692
693 pub fn write_out_commands(&self, w: &mut dyn Writer, version: GnuplotVersion)
694 {
695 if self.axis != TickAxis::CB
696 {
697 if self.show
698 {
699 w.write_str("set ");
700 w.write_str(self.axis.get_axis_str());
701 w.write_str("zeroaxis ");
702
703 AxesCommonData::write_color_options(
704 w,
705 &self.options,
706 false,
707 Some(ColorType::RGBString("black".into())),
708 );
709 AxesCommonData::write_line_options(w, &self.options, version);
710 }
711 else
712 {
713 w.write_str("unset ");
714 w.write_str(self.axis.get_axis_str());
715 w.write_str("zeroaxis ");
716 }
717 }
718
719 w.write_str("\n");
720
721 let log = match self.log_base
722 {
723 Some(base) =>
724 {
725 w.write_str("set logscale ");
726 w.write_str(self.axis.get_axis_str());
727 write!(w, " {:.12e}", base);
728 true
729 }
730 None =>
731 {
732 w.write_str("unset logscale ");
733 w.write_str(self.axis.get_axis_str());
734 false
735 }
736 };
737 w.write_str("\n");
738
739 w.write_str("set ");
740 w.write_str(self.axis.get_axis_str());
741 w.write_str("data");
742 if self.is_time
743 {
744 w.write_str(" time");
745 }
746 w.write_str("\n");
747
748 match self.tick_type
749 {
750 TickType::Auto(_, mticks) =>
751 {
752 write!(w, "set m{} ", self.axis.get_tick_str());
753 if log
754 {
755 writeln!(w, "default");
756 }
757 else
758 {
759 writeln!(w, "{}", mticks as i32 + 1);
760 }
761 }
762 _ =>
763 {
764 writeln!(w, "unset m{}", self.axis.get_tick_str());
765 }
766 }
767 w.write_str("\n");
768
769 w.write_str("set ");
770 w.write_str(self.axis.get_range_str());
771 w.write_str(" [");
772 match self.min
773 {
774 Fix(v) => write!(w, "{:.12e}", v),
775 Auto => w.write_str("*"),
776 };
777 w.write_str(":");
778 match self.max
779 {
780 Fix(v) => write!(w, "{:.12e}", v),
781 Auto => w.write_str("*"),
782 };
783 if self.reverse
784 {
785 w.write_str("] reverse\n");
786 }
787 else
788 {
789 w.write_str("]\n");
790 }
791
792 let mut write_tick_options = true;
793 match self.tick_type
794 {
795 TickType::None =>
796 {
797 write!(w, "unset {0}", self.axis.get_tick_str());
798 write_tick_options = false;
799 }
800 TickType::Auto(incr, _) =>
801 {
802 w.write_str("set ");
803 w.write_str(self.axis.get_tick_str());
804
805 match incr
806 {
807 Auto =>
808 {
809 w.write_str(" autofreq");
810 }
811 Fix(incr) =>
812 {
813 if incr <= 0.0
814 {
815 panic!("'incr' must be positive, but is actually {}", incr);
816 }
817 w.write_str(" ");
818 write!(w, " {:.12e}", incr);
819 }
820 }
821 }
822 TickType::Custom(ref ticks) =>
823 {
824 w.write_str("set ");
825 w.write_str(self.axis.get_tick_str());
826 w.write_str(" (");
827
828 let mut first = true;
829 for tick in ticks
830 {
831 if first
832 {
833 first = false;
834 }
835 else
836 {
837 w.write_str(",");
838 }
839
840 let a = Auto;
841 let (ref pos, label, level) = match *tick
842 {
843 Minor(ref pos) => (pos, &a, 1),
844 Major(ref pos, ref label) => (pos, label, 0),
845 };
846
847 match *label
848 {
849 Fix(ref label) =>
850 {
851 w.write_str("\"");
852 w.write_str(&label[..]);
853 w.write_str("\" ");
854 }
855 Auto => (),
856 }
857 write!(w, "{:.12e} {}", pos.get(), level);
858 }
859 w.write_str(")");
860 }
861 }
862
863 if write_tick_options
864 {
865 let label_options = &self.label_options;
866 let tick_options = &self.tick_options;
867
868 write_out_label_options(AxesTicks, &label_options[..], &mut *w);
869
870 first_opt! {tick_options,
871 OnAxis(b) =>
872 {
873 w.write_str(match b
874 {
875 true => " axis",
876 false => " border",
877 });
878 }
879 }
880
881 first_opt! {tick_options,
882 Mirror(b) =>
883 {
884 w.write_str(match b
885 {
886 true => " mirror",
887 false => " nomirror",
888 });
889 }
890 }
891
892 first_opt! {tick_options,
893 Inward(b) =>
894 {
895 w.write_str(match b
896 {
897 true => " in",
898 false => " out",
899 });
900 }
901 }
902
903 let mut minor_scale = 0.5;
904 let mut major_scale = 0.5;
905
906 first_opt! {tick_options,
907 MinorScale(s) =>
908 {
909 minor_scale = s;
910 }
911 }
912
913 first_opt! {tick_options,
914 MajorScale(s) =>
915 {
916 major_scale = s;
917 }
918 }
919
920 write!(w, " scale {:.12e},{:.12e}", major_scale, minor_scale);
921
922 first_opt! {tick_options,
923 Format(ref f) =>
924 {
925 write!(w, r#" format "{}""#, f);
926 }
927 }
928 }
929 w.write_str("\n");
930 self.label.write_out_commands(w);
931 w.write_str("\n");
932 }
933
934 pub fn set_ticks_custom<T: DataType, TL: IntoIterator<Item = Tick<T, String>>>(
935 &mut self, ticks: TL, tick_options: Vec<TickOption<String>>,
936 label_options: Vec<LabelOption<String>>,
937 )
938 {
939 self.tick_type = TickType::Custom(
940 ticks
941 .into_iter()
942 .map(|t| match t
943 {
944 Major(t, l) => Major(t.get(), l),
945 Minor(t) => Minor(t.get()),
946 })
947 .collect(),
948 );
949 self.tick_options = tick_options;
950 self.label_options = label_options;
951 }
952
953 pub fn set_ticks(
954 &mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
955 tick_options: Vec<TickOption<String>>, label_options: Vec<LabelOption<String>>,
956 )
957 {
958 if let Some((incr, mticks)) = tick_placement
959 {
960 self.tick_type = TickType::Auto(incr, mticks);
961 self.tick_options = tick_options;
962 self.label_options = label_options;
963 }
964 else
965 {
966 self.tick_type = TickType::None
967 }
968 }
969
970 pub fn set_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>)
971 {
972 self.min = min;
973 self.max = max;
974 }
975
976 pub fn set_log(&mut self, base: Option<f64>)
977 {
978 self.log_base = base;
979 }
980
981 pub fn set_reverse(&mut self, reverse: bool)
982 {
983 self.reverse = reverse;
984 }
985
986 pub fn set_grid(&mut self, show: bool)
987 {
988 self.grid = show;
989 }
990
991 pub fn set_minor_grid(&mut self, show: bool)
992 {
993 self.mgrid = show;
994 }
995
996 pub fn set_time(&mut self, is_time: bool)
997 {
998 self.is_time = is_time;
999 }
1000}
1001
1002pub fn char_to_symbol(c: char) -> i32
1003{
1004 match c
1005 {
1006 '.' => 0,
1007 '+' => 1,
1008 'x' => 2,
1009 '*' => 3,
1010 's' => 4,
1011 'S' => 5,
1012 'o' => 6,
1013 'O' => 7,
1014 't' => 8,
1015 'T' => 9,
1016 'd' => 10,
1017 'D' => 11,
1018 'r' => 12,
1019 'R' => 13,
1020 a => panic!("Invalid symbol {}", a),
1021 }
1022}
1023
1024enum DataSourceType
1025{
1026 Record,
1027 Array,
1028 SizedArray(f64, f64, f64, f64),
1029}
1030
1031pub struct Margins
1032{
1033 pub left: Option<f32>,
1034 pub right: Option<f32>,
1035 pub top: Option<f32>,
1036 pub bottom: Option<f32>,
1037}
1038
1039impl Default for Margins
1040{
1041 fn default() -> Self
1042 {
1043 Self::new()
1044 }
1045}
1046
1047impl Margins
1048{
1049 pub fn new() -> Self
1050 {
1051 Margins {
1052 left: None,
1053 right: None,
1054 top: None,
1055 bottom: None,
1056 }
1057 }
1058
1059 pub fn write_out_commands(&self, w: &mut dyn Writer)
1060 {
1061 let mut write_margin = |margin, v| {
1062 write!(w, "set {}", margin);
1063 if let Some(v) = v
1064 {
1065 write!(w, " at screen {}", v);
1066 }
1067 w.write_str("\n");
1068 };
1069
1070 write_margin("lmargin", self.left);
1071 write_margin("rmargin", self.right);
1072 write_margin("tmargin", self.top);
1073 write_margin("bmargin", self.bottom);
1074 }
1075}
1076
1077#[derive(Copy, Clone)]
1078pub struct Position
1079{
1080 x: f64,
1081 y: f64,
1082}
1083
1084#[derive(Copy, Clone)]
1085pub struct Size
1086{
1087 w: f64,
1088 h: f64,
1089}
1090
1091pub struct AxesCommonData
1092{
1093 pub grid_options: Vec<PlotOption<String>>,
1094 pub minor_grid_options: Vec<PlotOption<String>>,
1095 pub grid_front: bool,
1096 pub elems: Vec<PlotElement>,
1097 pub x_axis: AxisData,
1098 pub x2_axis: AxisData,
1099 pub y_axis: AxisData,
1100 pub y2_axis: AxisData,
1101 pub cb_axis: AxisData,
1102 pub labels: Vec<LabelData>,
1103 pub title: LabelData,
1104 pub position: Option<Position>,
1105 pub size: Option<Size>,
1106 pub aspect_ratio: AutoOption<f64>,
1107 pub margins: Margins,
1108 pub palette: PaletteType<Vec<(f32, f32, f32, f32)>>,
1109 pub colormaps: Vec<(String, PaletteType<Vec<(f32, f32, f32, f32)>>)>,
1110 pub box_width: Option<(f64, bool)>,
1111}
1112
1113impl AxesCommonData
1114{
1115 pub fn new() -> AxesCommonData
1116 {
1117 let mut ret = AxesCommonData {
1118 grid_options: vec![],
1119 minor_grid_options: vec![],
1120 grid_front: false,
1121 elems: Vec::new(),
1122 x_axis: AxisData::new(TickAxis::X),
1123 y_axis: AxisData::new(TickAxis::Y),
1124 x2_axis: AxisData::new(TickAxis::X2),
1125 y2_axis: AxisData::new(TickAxis::Y2),
1126 cb_axis: AxisData::new(TickAxis::CB),
1127 labels: vec![],
1128 title: LabelData::new(TitleLabel),
1129 position: None,
1130 size: None,
1131 aspect_ratio: Auto,
1132 margins: Margins::new(),
1133 palette: COLOR.to_one_way_owned(),
1134 colormaps: Vec::new(),
1135 box_width: None,
1136 };
1137 ret.x2_axis.tick_type = TickType::None;
1138 ret.y2_axis.tick_type = TickType::None;
1139 ret
1140 }
1141
1142 pub fn write_grid_options(&self, c: &mut dyn Writer, axes: &[TickAxis], version: GnuplotVersion)
1143 {
1144 if !axes.is_empty()
1145 {
1146 c.write_str("set grid ");
1147 for axis in axes
1148 {
1149 c.write_str(axis.get_tick_str());
1150 c.write_str(" ");
1151 if self.x_axis.axis == *axis && self.x_axis.mgrid
1152 || self.y_axis.axis == *axis && self.y_axis.mgrid
1153 || self.x2_axis.axis == *axis && self.x2_axis.mgrid
1154 || self.y2_axis.axis == *axis && self.y2_axis.mgrid
1155 {
1156 c.write_str(axis.get_mtick_str());
1157 c.write_str(" ");
1158 }
1159 }
1160
1161 if self.grid_front
1162 {
1163 c.write_str("front ");
1164 }
1165 else
1166 {
1167 c.write_str("back ");
1168 }
1169
1170 AxesCommonData::write_line_options(c, &self.grid_options, version);
1171 AxesCommonData::write_color_options(c, &self.grid_options, false, None);
1172 c.write_str(", ");
1173 AxesCommonData::write_line_options(c, &self.minor_grid_options, version);
1174 AxesCommonData::write_color_options(c, &self.minor_grid_options, false, None);
1175 c.write_str("\n");
1176 }
1177 }
1178
1179 pub fn write_line_options(
1180 c: &mut dyn Writer, options: &[PlotOption<String>], version: GnuplotVersion,
1181 )
1182 {
1183 let mut found = false;
1184 c.write_str(" lw ");
1185 first_opt! {options,
1186 LineWidth(w) =>
1187 {
1188 write!(c, "{:.12e}", w);
1189 found = true;
1190 }
1191 }
1192 if !found
1193 {
1194 c.write_str("1");
1195 }
1196
1197 if version.major >= 5
1198 {
1199 first_opt! {options,
1200 LineStyle(d) =>
1201 {
1202 write!(c, " dt {}", d.to_int());
1203 }
1204 }
1205 }
1206 else
1207 {
1208 first_opt! {options,
1209 LineStyle(d) =>
1210 {
1211 write!(c, " lt {}", d.to_int());
1212 }
1213 }
1214 }
1215 }
1216
1217 pub fn write_color_options(
1218 c: &mut dyn Writer, options: &[PlotOption<String>], is_fill: bool,
1219 default: Option<ColorType>,
1220 )
1221 {
1222 let main_type = if is_fill { "fillcolor" } else { "linecolor" };
1223
1224 let mut col = default.as_ref();
1225 first_opt! {options,
1226 Color(ref s) =>
1227 {
1228 col = Some(s)
1229 }
1230 }
1231 if let Some(s) = col
1232 {
1233 write!(c, " {main_type} {}", s.command());
1234 }
1235 }
1236
1237 pub fn write_out_commands(
1238 &self, writer: &mut dyn Writer, auto_layout: bool, version: GnuplotVersion,
1239 )
1240 {
1241 let w = writer;
1242 if let Some(pos) = self.position
1243 {
1244 writeln!(w, "set origin {:.12e},{:.12e}", pos.x, pos.y);
1245 }
1246 else if !auto_layout
1247 {
1248 writeln!(w, "set origin");
1249 }
1250 if let Some(size) = self.size
1251 {
1252 writeln!(w, "set size {:.12e},{:.12e}", size.w, size.h);
1253 }
1254 else if !auto_layout
1255 {
1256 writeln!(w, "set size");
1257 }
1258
1259 match self.aspect_ratio
1260 {
1261 Fix(r) =>
1262 {
1263 writeln!(w, "set size ratio {:.12e}", r);
1264 }
1265 Auto =>
1266 {
1267 writeln!(w, "set size noratio");
1268 }
1269 }
1270 self.margins.write_out_commands(w);
1271
1272 if !self.colormaps.is_empty()
1273 {
1274 for (name, map) in &self.colormaps
1275 {
1276 map.write_out_commands(w);
1277 writeln!(w, "set colormap new {name}");
1278 }
1279 }
1280 self.palette.write_out_commands(w);
1281
1282 if let Some((width, is_relative)) = self.box_width
1283 {
1284 let scale = if is_relative { "relative" } else { "absolute" };
1285 writeln!(w, "set boxwidth {width} {scale}");
1286 }
1287
1288 self.x_axis.write_out_commands(w, version);
1289 self.y_axis.write_out_commands(w, version);
1290 self.x2_axis.write_out_commands(w, version);
1291 self.y2_axis.write_out_commands(w, version);
1292 self.cb_axis.write_out_commands(w, version);
1293 self.title.write_out_commands(w);
1294 for label in &self.labels
1295 {
1296 label.write_out_commands(w);
1297 }
1298 }
1299
1300 pub fn write_out_elements(
1301 &self, cmd: &str, data_directory: Option<&str>, writer: &mut dyn Writer,
1302 version: GnuplotVersion,
1303 )
1304 {
1305 if let Some(data_directory) = data_directory
1306 {
1307 for (i, e) in self.elems.iter().enumerate()
1308 {
1309 let filename = path::Path::new(data_directory).join(format!("{i}.bin"));
1310 let mut file = fs::File::create(&filename).unwrap();
1311 e.write_data(&mut file);
1312 }
1313 }
1314
1315 write!(writer, "{}", cmd);
1316
1317 let mut first = true;
1318 for (i, e) in self.elems.iter().enumerate()
1319 {
1320 if e.num_rows == 0
1321 {
1322 continue;
1323 }
1324 if !first
1325 {
1326 write!(writer, ",");
1327 }
1328 let source = if let Some(data_directory) = data_directory
1329 {
1330 escape(
1331 path::Path::new(data_directory)
1332 .join(format!("{i}.bin"))
1333 .to_str()
1334 .unwrap(),
1335 )
1336 }
1337 else
1338 {
1339 "-".into()
1340 };
1341 e.write_args(&source, writer, version);
1342 first = false;
1343 }
1344
1345 writeln!(writer);
1346
1347 if data_directory.is_none()
1348 {
1349 for e in self.elems.iter()
1350 {
1351 e.write_data(writer);
1352 }
1353 }
1354 }
1355
1356 pub fn reset_state(&self, writer: &mut dyn Writer)
1357 {
1358 for label in &self.labels
1359 {
1360 label.reset_state(writer);
1361 }
1362 }
1363}
1364
1365#[doc(hidden)]
1366pub trait AxesCommonPrivate
1367{
1368 fn get_common_data(&self) -> &AxesCommonData;
1369 fn get_common_data_mut(&mut self) -> &mut AxesCommonData;
1370}
1371
1372pub trait AxesCommon: AxesCommonPrivate
1373{
1374 fn set_pos_grid(&mut self, nrow: u32, ncol: u32, pos: u32) -> &mut Self
1381 {
1382 assert!(nrow > 0);
1383 assert!(ncol > 0);
1384 assert!(pos < nrow * ncol);
1385 let width = 1.0 / (ncol as f64);
1386 let height = 1.0 / (nrow as f64);
1387 let x = (pos % ncol) as f64 * width;
1388 let y = 1.0 - (1.0 + (pos / ncol) as f64) * height;
1389
1390 self.get_common_data_mut().position = Some(Position { x, y });
1391 self.get_common_data_mut().size = Some(Size {
1392 w: width,
1393 h: height,
1394 });
1395 self
1396 }
1397
1398 fn set_pos(&mut self, x: f64, y: f64) -> &mut Self
1404 {
1405 self.get_common_data_mut().position = Some(Position { x, y });
1406 self
1407 }
1408
1409 fn set_size(&mut self, w: f64, h: f64) -> &mut Self
1414 {
1415 self.get_common_data_mut().size = Some(Size { w, h });
1416 self
1417 }
1418
1419 fn set_box_width(&mut self, width: f64, is_relative: bool) -> &mut Self
1426 {
1427 self.get_common_data_mut().box_width = Some((width, is_relative));
1428 self
1429 }
1430
1431 fn set_aspect_ratio(&mut self, ratio: AutoOption<f64>) -> &mut Self
1435 {
1436 self.get_common_data_mut().aspect_ratio = ratio;
1437 self
1438 }
1439
1440 fn set_x_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1450 {
1451 self.get_common_data_mut()
1452 .x_axis
1453 .label
1454 .set(text.into(), options.to_one_way_owned());
1455 self
1456 }
1457
1458 fn set_y_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1460 {
1461 self.get_common_data_mut()
1462 .y_axis
1463 .label
1464 .set(text.into(), options.to_one_way_owned());
1465 self
1466 }
1467
1468 fn set_x2_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1470 {
1471 self.get_common_data_mut()
1472 .x2_axis
1473 .label
1474 .set(text.into(), options.to_one_way_owned());
1475 self
1476 }
1477
1478 fn set_y2_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1480 {
1481 self.get_common_data_mut()
1482 .y2_axis
1483 .label
1484 .set(text.into(), options.to_one_way_owned());
1485 self
1486 }
1487
1488 fn set_cb_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1490 {
1491 self.get_common_data_mut()
1492 .cb_axis
1493 .label
1494 .set(text.into(), options.to_one_way_owned());
1495 self
1496 }
1497
1498 fn set_title<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1508 {
1509 self.get_common_data_mut()
1510 .title
1511 .set(text.into(), options.to_one_way_owned());
1512 self
1513 }
1514
1515 fn label<'l>(
1530 &'l mut self, text: &str, x: Coordinate, y: Coordinate, options: &[LabelOption<&str>],
1531 ) -> &'l mut Self
1532 {
1533 {
1534 let labels = &mut self.get_common_data_mut().labels;
1535 let mut label = LabelData::new(Label(labels.len() as i32 + 1, x, y));
1536 label.set(text.into(), options.to_one_way_owned());
1537 labels.push(label);
1538 }
1539 self
1540 }
1541
1542 fn set_x_ticks<'l>(
1557 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1558 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1559 ) -> &'l mut Self
1560 {
1561 self.get_common_data_mut().x_axis.set_ticks(
1562 tick_placement,
1563 tick_options.to_one_way_owned(),
1564 label_options.to_one_way_owned(),
1565 );
1566 self
1567 }
1568
1569 fn set_y_ticks<'l>(
1571 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1572 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1573 ) -> &'l mut Self
1574 {
1575 self.get_common_data_mut().y_axis.set_ticks(
1576 tick_placement,
1577 tick_options.to_one_way_owned(),
1578 label_options.to_one_way_owned(),
1579 );
1580 self
1581 }
1582
1583 fn set_x2_ticks<'l>(
1587 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1588 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1589 ) -> &'l mut Self
1590 {
1591 self.get_common_data_mut().y2_axis.set_ticks(
1592 tick_placement,
1593 tick_options.to_one_way_owned(),
1594 label_options.to_one_way_owned(),
1595 );
1596 self
1597 }
1598
1599 fn set_y2_ticks<'l>(
1603 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1604 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1605 ) -> &'l mut Self
1606 {
1607 self.get_common_data_mut().y2_axis.set_ticks(
1608 tick_placement,
1609 tick_options.to_one_way_owned(),
1610 label_options.to_one_way_owned(),
1611 );
1612 self
1613 }
1614
1615 fn set_cb_ticks<'l>(
1617 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1618 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1619 ) -> &'l mut Self
1620 {
1621 self.get_common_data_mut().cb_axis.set_ticks(
1622 tick_placement,
1623 tick_options.to_one_way_owned(),
1624 label_options.to_one_way_owned(),
1625 );
1626 self
1627 }
1628
1629 fn set_x_ticks_custom<
1644 'l,
1645 T: DataType,
1646 S: ToString,
1647 TickT: Borrow<Tick<T, S>>,
1648 TL: IntoIterator<Item = TickT>,
1649 >(
1650 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1651 label_options: &[LabelOption<&str>],
1652 ) -> &'l mut Self
1653 {
1654 self.get_common_data_mut().x_axis.set_ticks_custom(
1655 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1656 tick_options.to_one_way_owned(),
1657 label_options.to_one_way_owned(),
1658 );
1659 self
1660 }
1661
1662 fn set_y_ticks_custom<
1664 'l,
1665 T: DataType,
1666 S: ToString,
1667 TickT: Borrow<Tick<T, S>>,
1668 TL: IntoIterator<Item = TickT>,
1669 >(
1670 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1671 label_options: &[LabelOption<&str>],
1672 ) -> &'l mut Self
1673 {
1674 self.get_common_data_mut().y_axis.set_ticks_custom(
1675 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1676 tick_options.to_one_way_owned(),
1677 label_options.to_one_way_owned(),
1678 );
1679 self
1680 }
1681
1682 fn set_x2_ticks_custom<
1684 'l,
1685 T: DataType,
1686 S: ToString,
1687 TickT: Borrow<Tick<T, S>>,
1688 TL: IntoIterator<Item = TickT>,
1689 >(
1690 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1691 label_options: &[LabelOption<&str>],
1692 ) -> &'l mut Self
1693 {
1694 self.get_common_data_mut().x2_axis.set_ticks_custom(
1695 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1696 tick_options.to_one_way_owned(),
1697 label_options.to_one_way_owned(),
1698 );
1699 self
1700 }
1701
1702 fn set_y2_ticks_custom<
1704 'l,
1705 T: DataType,
1706 S: ToString,
1707 TickT: Borrow<Tick<T, S>>,
1708 TL: IntoIterator<Item = TickT>,
1709 >(
1710 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1711 label_options: &[LabelOption<&str>],
1712 ) -> &'l mut Self
1713 {
1714 self.get_common_data_mut().y2_axis.set_ticks_custom(
1715 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1716 tick_options.to_one_way_owned(),
1717 label_options.to_one_way_owned(),
1718 );
1719 self
1720 }
1721
1722 fn set_cb_ticks_custom<
1724 'l,
1725 T: DataType,
1726 S: ToString,
1727 TickT: Borrow<Tick<T, S>>,
1728 TL: IntoIterator<Item = TickT>,
1729 >(
1730 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1731 label_options: &[LabelOption<&str>],
1732 ) -> &'l mut Self
1733 {
1734 self.get_common_data_mut().cb_axis.set_ticks_custom(
1735 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1736 tick_options.to_one_way_owned(),
1737 label_options.to_one_way_owned(),
1738 );
1739 self
1740 }
1741
1742 fn set_x_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1748 {
1749 self.get_common_data_mut().x_axis.set_range(min, max);
1750 self
1751 }
1752
1753 fn set_y_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1759 {
1760 self.get_common_data_mut().y_axis.set_range(min, max);
1761 self
1762 }
1763
1764 fn set_x2_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1770 {
1771 self.get_common_data_mut().x2_axis.set_range(min, max);
1772 self
1773 }
1774
1775 fn set_y2_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1781 {
1782 self.get_common_data_mut().y2_axis.set_range(min, max);
1783 self
1784 }
1785
1786 fn set_x_reverse(&mut self, reverse: bool) -> &mut Self
1790 {
1791 self.get_common_data_mut().x_axis.set_reverse(reverse);
1792 self
1793 }
1794
1795 fn set_y_reverse(&mut self, reverse: bool) -> &mut Self
1799 {
1800 self.get_common_data_mut().y_axis.set_reverse(reverse);
1801 self
1802 }
1803
1804 fn set_x2_reverse(&mut self, reverse: bool) -> &mut Self
1808 {
1809 self.get_common_data_mut().x2_axis.set_reverse(reverse);
1810 self
1811 }
1812
1813 fn set_y2_reverse(&mut self, reverse: bool) -> &mut Self
1817 {
1818 self.get_common_data_mut().y2_axis.set_reverse(reverse);
1819 self
1820 }
1821
1822 fn set_cb_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1828 {
1829 self.get_common_data_mut().cb_axis.set_range(min, max);
1830 self
1831 }
1832
1833 fn set_x_log(&mut self, base: Option<f64>) -> &mut Self
1838 {
1839 self.get_common_data_mut().x_axis.set_log(base);
1840 self
1841 }
1842
1843 fn set_y_log(&mut self, base: Option<f64>) -> &mut Self
1848 {
1849 self.get_common_data_mut().y_axis.set_log(base);
1850 self
1851 }
1852
1853 fn set_x2_log(&mut self, base: Option<f64>) -> &mut Self
1858 {
1859 self.get_common_data_mut().x2_axis.set_log(base);
1860 self
1861 }
1862
1863 fn set_y2_log(&mut self, base: Option<f64>) -> &mut Self
1868 {
1869 self.get_common_data_mut().y2_axis.set_log(base);
1870 self
1871 }
1872
1873 fn set_cb_log(&mut self, base: Option<f64>) -> &mut Self
1878 {
1879 self.get_common_data_mut().cb_axis.set_log(base);
1880 self
1881 }
1882
1883 fn set_x_grid(&mut self, show: bool) -> &mut Self
1888 {
1889 self.get_common_data_mut().x_axis.set_grid(show);
1890 self
1891 }
1892
1893 fn set_x_minor_grid(&mut self, show: bool) -> &mut Self
1898 {
1899 self.get_common_data_mut().x_axis.set_minor_grid(show);
1900 self
1901 }
1902
1903 fn set_y_grid(&mut self, show: bool) -> &mut Self
1908 {
1909 self.get_common_data_mut().y_axis.set_grid(show);
1910 self
1911 }
1912
1913 fn set_y_minor_grid(&mut self, show: bool) -> &mut Self
1918 {
1919 self.get_common_data_mut().y_axis.set_minor_grid(show);
1920 self
1921 }
1922
1923 fn set_x2_grid(&mut self, show: bool) -> &mut Self
1928 {
1929 self.get_common_data_mut().x2_axis.set_grid(show);
1930 self
1931 }
1932
1933 fn set_x2_minor_grid(&mut self, show: bool) -> &mut Self
1938 {
1939 self.get_common_data_mut().x2_axis.set_minor_grid(show);
1940 self
1941 }
1942
1943 fn set_y2_grid(&mut self, show: bool) -> &mut Self
1948 {
1949 self.get_common_data_mut().y2_axis.set_grid(show);
1950 self
1951 }
1952
1953 fn set_y2_minor_grid(&mut self, show: bool) -> &mut Self
1958 {
1959 self.get_common_data_mut().y2_axis.set_minor_grid(show);
1960 self
1961 }
1962
1963 fn set_cb_grid(&mut self, show: bool) -> &mut Self
1968 {
1969 self.get_common_data_mut().cb_axis.set_grid(show);
1970 self
1971 }
1972
1973 fn set_grid_options<'l>(&'l mut self, front: bool, options: &[PlotOption<&str>])
1982 -> &'l mut Self
1983 {
1984 self.get_common_data_mut().grid_front = front;
1985 self.get_common_data_mut().grid_options = options.to_one_way_owned();
1986 self
1987 }
1988
1989 fn set_minor_grid_options<'l>(&'l mut self, options: &[PlotOption<&str>]) -> &'l mut Self
1997 {
1998 self.get_common_data_mut().minor_grid_options = options.to_one_way_owned();
1999 self
2000 }
2001
2002 fn set_x_time(&mut self, is_time: bool) -> &mut Self
2010 {
2011 self.get_common_data_mut().x_axis.set_time(is_time);
2012 self
2013 }
2014
2015 fn set_y_time(&mut self, is_time: bool) -> &mut Self
2023 {
2024 self.get_common_data_mut().y_axis.set_time(is_time);
2025 self
2026 }
2027
2028 fn set_x2_time(&mut self, is_time: bool) -> &mut Self
2036 {
2037 self.get_common_data_mut().x2_axis.set_time(is_time);
2038 self
2039 }
2040
2041 fn set_y2_time(&mut self, is_time: bool) -> &mut Self
2049 {
2050 self.get_common_data_mut().y2_axis.set_time(is_time);
2051 self
2052 }
2053
2054 fn set_cb_time(&mut self, is_time: bool) -> &mut Self
2062 {
2063 self.get_common_data_mut().cb_axis.set_time(is_time);
2064 self
2065 }
2066
2067 fn set_margins(&mut self, margins: &[MarginSide]) -> &mut Self
2074 {
2075 {
2076 let m = &mut self.get_common_data_mut().margins;
2077 *m = Margins::new();
2078 for &s in margins.iter()
2079 {
2080 match s
2081 {
2082 MarginLeft(frac) => m.left = Some(frac),
2083 MarginRight(frac) => m.right = Some(frac),
2084 MarginTop(frac) => m.top = Some(frac),
2085 MarginBottom(frac) => m.bottom = Some(frac),
2086 };
2087 }
2088 }
2089 self
2090 }
2091
2092 fn set_palette(&mut self, palette: PaletteType<&[(f32, f32, f32, f32)]>) -> &mut Self
2098 {
2099 self.get_common_data_mut().palette = palette.to_one_way_owned();
2100 self
2101 }
2102
2103 fn create_colormap(
2110 &mut self, name: &str, palette: PaletteType<&[(f32, f32, f32, f32)]>,
2111 ) -> &mut Self
2112 {
2113 self.get_common_data_mut()
2114 .colormaps
2115 .push((name.to_owned(), palette.to_one_way_owned()));
2116 self
2117 }
2118}