1use display::DisplayColor;
2
3use super::LineSegment;
4
5#[derive(Debug)]
7pub struct ViewLine {
8 pinned_segments: usize,
9 segments: Vec<LineSegment>,
10 selected: bool,
11 padding: Option<LineSegment>,
12}
13
14impl ViewLine {
15 #[must_use]
17 #[inline]
18 pub fn new_empty_line() -> Self {
19 Self::new_with_pinned_segments(vec![], 1)
20 }
21
22 #[must_use]
24 #[inline]
25 pub fn new_pinned(segments: Vec<LineSegment>) -> Self {
26 let segments_length = segments.len();
27 Self::new_with_pinned_segments(segments, segments_length)
28 }
29
30 #[must_use]
32 #[inline]
33 pub fn new_with_pinned_segments(segments: Vec<LineSegment>, pinned_segments: usize) -> Self {
34 Self {
35 selected: false,
36 segments,
37 pinned_segments,
38 padding: None,
39 }
40 }
41
42 #[must_use]
44 #[inline]
45 pub const fn set_selected(mut self, selected: bool) -> Self {
46 self.selected = selected;
47 self
48 }
49
50 #[must_use]
52 #[inline]
53 pub fn set_padding(mut self, c: char) -> Self {
54 self.padding = Some(LineSegment::new(String::from(c).as_str()));
55 self
56 }
57
58 #[must_use]
60 #[inline]
61 pub fn set_padding_with_color_and_style(
62 mut self,
63 c: char,
64 color: DisplayColor,
65 dim: bool,
66 underline: bool,
67 reverse: bool,
68 ) -> Self {
69 self.padding = Some(LineSegment::new_with_color_and_style(
70 String::from(c).as_str(),
71 color,
72 dim,
73 underline,
74 reverse,
75 ));
76 self
77 }
78
79 #[must_use]
81 #[inline]
82 pub const fn get_number_of_pinned_segment(&self) -> usize {
83 self.pinned_segments
84 }
85
86 #[must_use]
88 #[inline]
89 pub const fn get_segments(&self) -> &Vec<LineSegment> {
90 &self.segments
91 }
92
93 #[must_use]
95 #[inline]
96 pub const fn get_selected(&self) -> bool {
97 self.selected
98 }
99
100 pub(crate) const fn get_padding(&self) -> &Option<LineSegment> {
101 &self.padding
102 }
103}
104
105impl From<&str> for ViewLine {
106 #[inline]
107 fn from(line: &str) -> Self {
108 Self::from(LineSegment::new(line))
109 }
110}
111
112impl From<String> for ViewLine {
113 #[inline]
114 fn from(line: String) -> Self {
115 Self::from(LineSegment::new(line.as_str()))
116 }
117}
118
119impl From<LineSegment> for ViewLine {
120 #[inline]
121 fn from(line_segment: LineSegment) -> Self {
122 Self::from(vec![line_segment])
123 }
124}
125
126impl From<Vec<LineSegment>> for ViewLine {
127 #[inline]
128 fn from(line_segment: Vec<LineSegment>) -> Self {
129 Self::new_with_pinned_segments(line_segment, 0)
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn from_str() {
139 let view_line = ViewLine::from("foo");
140
141 assert_eq!(view_line.get_number_of_pinned_segment(), 0);
142 assert_eq!(view_line.get_segments().len(), 1);
143 assert_eq!(view_line.get_segments().first().unwrap().get_content(), "foo");
144 assert!(!view_line.get_selected());
145 }
146
147 #[test]
148 fn from_string() {
149 let view_line = ViewLine::from(String::from("foo"));
150
151 assert_eq!(view_line.get_number_of_pinned_segment(), 0);
152 assert_eq!(view_line.get_segments().len(), 1);
153 assert_eq!(view_line.get_segments().first().unwrap().get_content(), "foo");
154 assert!(!view_line.get_selected());
155 }
156
157 #[test]
158 fn from_line_segment() {
159 let view_line = ViewLine::from(LineSegment::new("foo"));
160
161 assert_eq!(view_line.get_number_of_pinned_segment(), 0);
162 assert_eq!(view_line.get_segments().len(), 1);
163 assert_eq!(view_line.get_segments().first().unwrap().get_content(), "foo");
164 assert!(!view_line.get_selected());
165 }
166
167 #[test]
168 fn from_list_line_segment() {
169 let view_line = ViewLine::from(vec![LineSegment::new("foo"), LineSegment::new("bar")]);
170
171 assert_eq!(view_line.get_number_of_pinned_segment(), 0);
172 assert_eq!(view_line.get_segments().len(), 2);
173 assert_eq!(view_line.get_segments().first().unwrap().get_content(), "foo");
174 assert_eq!(view_line.get_segments().last().unwrap().get_content(), "bar");
175 assert!(!view_line.get_selected());
176 }
177
178 #[test]
179 fn new_selected() {
180 let view_line = ViewLine::from(vec![LineSegment::new("foo"), LineSegment::new("bar")]).set_selected(true);
181
182 assert_eq!(view_line.get_number_of_pinned_segment(), 0);
183 assert_eq!(view_line.get_segments().len(), 2);
184 assert!(view_line.get_selected());
185 }
186
187 #[test]
188 fn new_pinned() {
189 let view_line = ViewLine::new_pinned(vec![
190 LineSegment::new("foo"),
191 LineSegment::new("bar"),
192 LineSegment::new("baz"),
193 LineSegment::new("foobar"),
194 ]);
195
196 assert_eq!(view_line.get_number_of_pinned_segment(), 4);
197 assert_eq!(view_line.get_segments().len(), 4);
198 assert!(!view_line.get_selected());
199 }
200
201 #[test]
202 fn new_with_pinned_segments() {
203 let view_line = ViewLine::new_with_pinned_segments(
204 vec![
205 LineSegment::new("foo"),
206 LineSegment::new("bar"),
207 LineSegment::new("baz"),
208 LineSegment::new("foobar"),
209 ],
210 2,
211 );
212
213 assert_eq!(view_line.get_number_of_pinned_segment(), 2);
214 assert_eq!(view_line.get_segments().len(), 4);
215 assert!(!view_line.get_selected());
216 }
217
218 #[test]
219 fn set_padding_with_color_and_style() {
220 let view_line =
221 ViewLine::from("foo").set_padding_with_color_and_style(' ', DisplayColor::IndicatorColor, true, true, true);
222
223 let padding = view_line.get_padding().as_ref().unwrap();
224 assert_eq!(padding.get_content(), " ");
225 assert_eq!(padding.get_color(), DisplayColor::IndicatorColor);
226 assert!(padding.is_dimmed());
227 assert!(padding.is_underlined());
228 assert!(padding.is_reversed());
229 }
230
231 #[test]
232 fn set_padding() {
233 let view_line = ViewLine::from("foo").set_padding('@');
234
235 assert_eq!(view_line.get_padding().as_ref().unwrap().get_content(), "@");
236 }
237}