gnuplot/
axes_common.rs

1// Copyright (c) 2013-2014 by SiegeLord
2//
3// All rights reserved. Distributed under LGPL 3.0. For full terms see the file LICENSE.
4
5use 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		// TODO: Reserve.
57		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 => (),  // This is the default behavior.
190						}
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				// Write this unconditionally so the write_line_options work below.
236				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	/// Set the position of the axes on the figure using grid coordinates.
1375	/// # Arguments
1376	/// * `nrow` - Number of rows in the grid. Must be greater than 0.
1377	/// * `ncol` - Number of columns in the grid. Must be greater than 0.
1378	/// * `pos` - Which grid cell to place this axes in, counting from top-left corner,
1379	///           going left and then down, starting at 0.
1380	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	/// Set the position of the axes on the figure using screen coordinates.
1399	/// The coordinates refer to the bottom-left corner of the axes
1400	/// # Arguments
1401	/// * `x` - X position. Ranges from 0 to 1
1402	/// * `y` - Y position. Ranges from 0 to 1
1403	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	/// Set the size of the axes
1410	/// # Arguments
1411	/// * `w` - Width. Ranges from 0 to 1
1412	/// * `h` - Height. Ranges from 0 to 1
1413	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	/// Set the width of boxes in any box plots on the axes (for example [boxes()](crate::Axes2D::boxes),
1420	/// [box_and_whisker()](crate::Axes2D::box_and_whisker))
1421	/// # Arguments
1422	/// * `width` - Width of boxes.
1423	/// * `is_relative` - if `true`, `width` is interpreted as a fraction of the default box width.
1424	/// 	if `false` width is an absolute value in the units of the x axis
1425	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	/// Set the aspect ratio of the axes
1432	/// # Arguments
1433	/// * `ratio` - The aspect ratio. Set to Auto to return the ratio to default
1434	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	/// Set the label for the X axis
1441	/// # Arguments
1442	/// * `text` - Text of the label. Pass an empty string to hide the label
1443	/// * `options` - Array of LabelOption controlling the appearance of the label. Relevant options are:
1444	///      * `Offset` - Specifies the offset of the label
1445	///      * `Font` - Specifies the font of the label
1446	///      * `TextColor` - Specifies the color of the label
1447	///      * `Rotate` - Specifies the rotation of the label
1448	///      * `Align` - Specifies how to align the label
1449	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	/// Like `set_x_label`, but for the Y axis
1459	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	/// Like `set_x_label`, but for the secondary X axis
1469	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	/// Like `set_x_label`, but for the secondary Y axis
1479	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	/// Like `set_x_label`, but for the color bar
1489	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	/// Set the title for the axes
1499	/// # Arguments
1500	/// * `text` - Text of the title. Pass an empty string to hide the title
1501	/// * `options` - Array of LabelOption<&str> controlling the appearance of the title. Relevant options are:
1502	///      * `Offset` - Specifies the offset of the label
1503	///      * `Font` - Specifies the font of the label
1504	///      * `TextColor` - Specifies the color of the label
1505	///      * `Rotate` - Specifies the rotation of the label
1506	///      * `Align` - Specifies how to align the label
1507	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	/// Adds a label to the plot, with an optional marker.
1516	/// # Arguments
1517	/// * `text` - Text of the label
1518	/// * `x` - X coordinate of the label
1519	/// * `y` - Y coordinate of the label
1520	/// * `options` - Array of LabelOption<&str> controlling the appearance of the label. Relevant options are:
1521	///      * `Offset` - Specifies the offset of the label
1522	///      * `Font` - Specifies the font of the label
1523	///      * `TextColor` - Specifies the color of the label
1524	///      * `Rotate` - Specifies the rotation of the label
1525	///      * `Align` - Specifies how to align the label
1526	///      * `MarkerSymbol` - Specifies the symbol for the marker. Omit to hide the marker
1527	///      * `MarkerSize` - Specifies the size for the marker
1528	///      * `MarkerColor` - Specifies the color for the marker
1529	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	/// Sets the properties of the ticks on the X axis.
1543	///
1544	/// # Arguments
1545	/// * `tick_placement` - Controls the placement of the ticks. Pass `None` to hide the ticks. Otherwise, the first tuple value controls the spacing
1546	///                      of the major ticks (in axes units), otherwise set it to `Auto` to let gnuplot decide the spacing automatically. The second
1547	///                      tuple value specifies the number of minor ticks. For logarithmic axes, non-zero values mean that the number of ticks usually
1548	///                      equals to `ceil(log_base) - 2`.
1549	/// * `tick_options` - Array of TickOption controlling the appearance of the ticks
1550	/// * `label_options` - Array of LabelOption<&str> controlling the appearance of the tick labels. Relevant options are:
1551	///      * `Offset` - Specifies the offset of the label
1552	///      * `Font` - Specifies the font of the label
1553	///      * `TextColor` - Specifies the color of the label
1554	///      * `Rotate` - Specifies the rotation of the label
1555	///      * `Align` - Specifies how to align the label
1556	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	/// Like `set_x_ticks` but for the Y axis.
1570	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	/// Like `set_x_ticks` but for the secondary X axis.
1584	///
1585	/// Note that by default, these are hidden.
1586	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	/// Like `set_x_ticks` but for the secondary Y axis.
1600	///
1601	/// Note that by default, these are hidden.
1602	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	/// Like `set_x_ticks` but for the color bar axis.
1616	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	/// Sets ticks on the X axis with specified labels at specified positions.
1630	///
1631	/// # Arguments
1632	///
1633	/// * `ticks` - The locations and labels of the added ticks.
1634	///     The label can contain a single C printf style floating point formatting specifier which will be replaced by the
1635	///     location of the tic.
1636	/// * `tick_options` - Array of TickOption controlling the appearance of the ticks
1637	/// * `label_options` - Array of LabelOption<&str> controlling the appearance of the tick labels. Relevant options are:
1638	///      * `Offset` - Specifies the offset of the label
1639	///      * `Font` - Specifies the font of the label
1640	///      * `TextColor` - Specifies the color of the label
1641	///      * `Rotate` - Specifies the rotation of the label
1642	///      * `Align` - Specifies how to align the label
1643	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	/// Like `set_x_ticks_custom` but for the the Y axis.
1663	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	/// Like `set_x_ticks_custom` but for the the secondary X axis.
1683	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	/// Like `set_x_ticks_custom` but for the the secondary Y axis.
1703	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	/// Like `set_x_ticks_custom` but for the the color bar axis.
1723	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	/// Set the range of values for the X axis.
1743	///
1744	/// # Arguments
1745	/// * `min` - Minimum X value
1746	/// * `max` - Maximum X value
1747	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	/// Set the range of values for the Y axis.
1754	///
1755	/// # Arguments
1756	/// * `min` - Minimum Y value
1757	/// * `max` - Maximum Y value
1758	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	/// Set the range of values for the secondary X axis.
1765	///
1766	/// # Arguments
1767	/// * `min` - Minimum X value
1768	/// * `max` - Maximum X value
1769	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	/// Set the range of values for the secondary Y axis.
1776	///
1777	/// # Arguments
1778	/// * `min` - Minimum Y value
1779	/// * `max` - Maximum Y value
1780	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	/// Sets X axis to reverse.
1787	/// # Arguments
1788	/// * `reverse` - Boolean, true to reverse axis, false will not reverse
1789	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	/// Sets Y axis to reverse.
1796	/// # Arguments
1797	/// * `reverse` - Boolean, true to reverse axis, false will not reverse
1798	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	/// Sets secondary X axis to reverse.
1805	/// # Arguments
1806	/// * `reverse` - Boolean, true to reverse axis, false will not reverse
1807	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	/// Sets secondary Y axis to reverse.
1814	/// # Arguments
1815	/// * `reverse` - Boolean, true to reverse axis, false will not reverse
1816	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	/// Set the range of values for the color bar axis.
1823	///
1824	/// # Arguments
1825	/// * `min` - Minimum Y value
1826	/// * `max` - Maximum Y value
1827	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	/// Sets the X axis be logarithmic. Note that the range must be non-negative for this to be valid.
1834	///
1835	/// # Arguments
1836	/// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1837	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	/// Sets the Y axis be logarithmic. Note that the range must be non-negative for this to be valid.
1844	///
1845	/// # Arguments
1846	/// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1847	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	/// Sets the secondary X axis be logarithmic. Note that the range must be non-negative for this to be valid.
1854	///
1855	/// # Arguments
1856	/// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1857	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	/// Sets the secondary Y axis be logarithmic. Note that the range must be non-negative for this to be valid.
1864	///
1865	/// # Arguments
1866	/// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1867	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	/// Sets the color bar axis be logarithmic. Note that the range must be non-negative for this to be valid.
1874	///
1875	/// # Arguments
1876	/// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1877	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	/// Shows the grid on the X axis.
1884	///
1885	/// # Arguments
1886	/// * `show` - Whether to show the grid.
1887	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	/// Shows the minor grid on the X axis.
1894	///
1895	/// # Arguments
1896	/// * `show` - Whether to show the grid.
1897	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	/// Shows the grid on the Y axis.
1904	///
1905	/// # Arguments
1906	/// * `show` - Whether to show the grid.
1907	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	/// Shows the minor grid on the Y axis.
1914	///
1915	/// # Arguments
1916	/// * `show` - Whether to show the grid.
1917	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	/// Shows the grid on the secondary X axis.
1924	///
1925	/// # Arguments
1926	/// * `show` - Whether to show the grid.
1927	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	/// Shows the minor grid on the secondary X axis.
1934	///
1935	/// # Arguments
1936	/// * `show` - Whether to show the grid.
1937	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	/// Shows the grid on the secondary Y axis.
1944	///
1945	/// # Arguments
1946	/// * `show` - Whether to show the grid.
1947	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	/// Shows the minor grid on the secondary Y axis.
1954	///
1955	/// # Arguments
1956	/// * `show` - Whether to show the grid.
1957	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	/// Shows the grid on the color bar axis.
1964	///
1965	/// # Arguments
1966	/// * `show` - Whether to show the grid.
1967	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	/// Set the grid options.
1974	///
1975	/// # Arguments
1976	/// * `front` - Whether the grid should be in the front of the plot elements or behind them.
1977	/// * `options` - Styling options of the grid. Relevant options are:
1978	///      * `Color` - Specifies the color of the grid lines
1979	///      * `LineStyle` - Specifies the style of the grid lines
1980	///      * `LineWidth` - Specifies the width of the grid lines
1981	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	/// Set the minor grid options.
1990	///
1991	/// # Arguments
1992	/// * `options` - Styling options of the grid. Relevant options are:
1993	///      * `Color` - Specifies the color of the grid lines
1994	///      * `LineStyle` - Specifies the style of the grid lines
1995	///      * `LineWidth` - Specifies the width of the grid lines
1996	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	/// Sets the X axis be time.
2003	///
2004	/// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2005	/// specify the formatting of the ticks (see strftime format spec for valid values).
2006	///
2007	/// # Arguments
2008	/// * `is_time` - Whether this axis is time or not.
2009	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	/// Sets the Y axis be time. Note that the range must be non-negative for this to be valid.
2016	///
2017	/// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2018	/// specify the formatting of the ticks (see strftime format spec for valid values).
2019	///
2020	/// # Arguments
2021	/// * `is_time` - Whether this axis is time or not.
2022	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	/// Sets the secondary X axis be time.
2029	///
2030	/// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2031	/// specify the formatting of the ticks (see strftime format spec for valid values).
2032	///
2033	/// # Arguments
2034	/// * `is_time` - Whether this axis is time or not.
2035	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	/// Sets the secondary Y axis be time. Note that the range must be non-negative for this to be valid.
2042	///
2043	/// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2044	/// specify the formatting of the ticks (see strftime format spec for valid values).
2045	///
2046	/// # Arguments
2047	/// * `is_time` - Whether this axis is time or not.
2048	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	/// Sets the color bar axis be time. Note that the range must be non-negative for this to be valid.
2055	///
2056	/// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2057	/// specify the formatting of the ticks (see strftime format spec for valid values).
2058	///
2059	/// # Arguments
2060	/// * `is_time` - Whether this axis is time or not.
2061	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	/// Sets the margins of the plot.
2068	///
2069	/// # Arguments
2070	///
2071	/// * `margins` - The values of margins to be overriden. Specified as a fraction of the
2072	///               full drawing area, ranging from 0 to 1
2073	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	/// Sets the palette used for 3D surface and image plots. See the [palettes][crate::palettes]
2093	/// module for a list of predefined palettes.
2094	///
2095	/// # Arguments
2096	/// * `palette` - What palette type to use
2097	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	/// Creates and saves a colormap in the gnuplot environment that can be used for
2104	/// later plots (see examples/color_variable.rs for example usage)
2105	///
2106	/// # Arguments
2107	/// * `name` - The name with which to save the colormap
2108	/// * `palette` - What palette type to use
2109	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}