1use crate::theme::{LegendPosition, Theme};
2
3use super::Rect;
4
5pub struct PlotLayout {
7 pub total: Rect,
8 pub plot_area: Rect,
9 pub title_area: Rect,
10 pub subtitle_area: Rect,
11 pub caption_area: Rect,
12 pub x_axis_area: Rect,
13 pub y_axis_area: Rect,
14 pub legend_area: Rect,
15}
16
17impl PlotLayout {
18 pub fn compute(
20 width: f64,
21 height: f64,
22 theme: &Theme,
23 has_title: bool,
24 has_legend: bool,
25 ) -> Self {
26 Self::compute_full(width, height, theme, has_title, false, false, has_legend)
27 }
28
29 pub fn compute_full(
31 width: f64,
32 height: f64,
33 theme: &Theme,
34 has_title: bool,
35 has_subtitle: bool,
36 has_caption: bool,
37 has_legend: bool,
38 ) -> Self {
39 let margin = &theme.plot_margin;
40
41 let title_height = if has_title {
42 theme.title.size * 2.0
43 } else {
44 0.0
45 };
46
47 let subtitle_height = if has_subtitle {
48 theme.subtitle.size * 1.5
49 } else {
50 0.0
51 };
52
53 let caption_height = if has_caption {
54 theme.caption.size * 1.8
55 } else {
56 0.0
57 };
58
59 let x_axis_height = theme.axis_ticks_length
60 + if theme.axis_text_x.visible {
61 theme.axis_text_x.size + 4.0
62 } else {
63 0.0
64 }
65 + if theme.axis_title_x.visible {
66 theme.axis_title_x.size + 8.0
67 } else {
68 0.0
69 };
70
71 let y_axis_width = theme.axis_ticks_length
72 + if theme.axis_text_y.visible {
73 theme.axis_text_y.size * 3.5 + 4.0
74 } else {
75 0.0
76 }
77 + if theme.axis_title_y.visible {
78 theme.axis_title_y.size + 8.0
79 } else {
80 0.0
81 };
82
83 let legend_size = if has_legend {
84 theme.legend_margin.left
85 + theme.legend_key_width
86 + theme.legend_spacing
87 + theme.legend_text.size * 6.0
88 + theme.legend_margin.right
89 } else {
90 0.0
91 };
92
93 let (legend_right, legend_left, legend_top, legend_bottom) = if has_legend {
95 match theme.legend_position {
96 LegendPosition::Right => (legend_size, 0.0, 0.0, 0.0),
97 LegendPosition::Left => (0.0, legend_size, 0.0, 0.0),
98 LegendPosition::Top => (0.0, 0.0, legend_size, 0.0),
99 LegendPosition::Bottom => (0.0, 0.0, 0.0, legend_size),
100 LegendPosition::None => (0.0, 0.0, 0.0, 0.0),
101 }
102 } else {
103 (0.0, 0.0, 0.0, 0.0)
104 };
105
106 let plot_x = margin.left + y_axis_width + legend_left;
107 let plot_y = margin.top + title_height + subtitle_height + legend_top;
108 let plot_width =
109 width - margin.left - margin.right - y_axis_width - legend_right - legend_left;
110 let plot_height = height
111 - margin.top
112 - margin.bottom
113 - title_height
114 - subtitle_height
115 - caption_height
116 - x_axis_height
117 - legend_top
118 - legend_bottom;
119
120 let plot_width = plot_width.max(50.0);
121 let plot_height = plot_height.max(50.0);
122
123 PlotLayout {
124 total: Rect {
125 x: 0.0,
126 y: 0.0,
127 width,
128 height,
129 },
130 plot_area: Rect {
131 x: plot_x,
132 y: plot_y,
133 width: plot_width,
134 height: plot_height,
135 },
136 title_area: Rect {
137 x: plot_x,
138 y: margin.top,
139 width: plot_width,
140 height: title_height,
141 },
142 subtitle_area: Rect {
143 x: plot_x,
144 y: margin.top + title_height,
145 width: plot_width,
146 height: subtitle_height,
147 },
148 caption_area: Rect {
149 x: plot_x,
150 y: plot_y + plot_height + x_axis_height,
151 width: plot_width,
152 height: caption_height,
153 },
154 x_axis_area: Rect {
155 x: plot_x,
156 y: plot_y + plot_height,
157 width: plot_width,
158 height: x_axis_height,
159 },
160 y_axis_area: Rect {
161 x: margin.left + legend_left,
162 y: plot_y,
163 width: y_axis_width,
164 height: plot_height,
165 },
166 legend_area: Rect {
167 x: plot_x + plot_width,
168 y: plot_y,
169 width: legend_size,
170 height: plot_height,
171 },
172 }
173 }
174}