1use std::cmp;
2
3use textwrap::core::display_width;
4
5use crate::{
6 align::{get_lines, get_strs_height},
7 whitespace::{WhiteSpace, WhiteSpaceType},
8};
9
10#[derive(Clone, Copy, Debug)]
11pub enum Position {
12 Top,
13 Bottom,
14 Center,
15 Left,
16 Right,
17}
18
19pub fn place(
20 width: i32,
21 height: i32,
22 h_pos: Position,
23 v_pos: Position,
24 strs: String,
25 opts: &[WhiteSpaceType],
26) -> String {
27 return place_vertical(
28 height,
29 v_pos,
30 place_horizontal(width, h_pos, strs, opts),
31 opts,
32 );
33}
34
35pub fn place_horizontal(
36 width: i32,
37 pos: Position,
38 strs: String,
39 opts: &[WhiteSpaceType],
40) -> String {
41 let binding = strs.to_string();
42 let (lines, content_width) = get_lines(&binding);
43 let gap = width as usize - content_width;
44 if gap <= 0 {
45 return strs;
46 }
47
48 let mut ws = WhiteSpace::new(opts);
49
50 let mut b = String::new();
51
52 for (i, line) in lines.clone().enumerate() {
53 let short = cmp::max(0, content_width - display_width(line));
54 match pos {
55 Position::Left => {
56 b.push_str(&line);
57 b.push_str(&ws.render(gap + short));
58 }
59 Position::Right => {
60 b.push_str(&ws.render(gap + short));
61 b.push_str(&line);
62 }
63 _ => {
64 let left = (gap + short) / 2;
65 let right = (gap + short) / 2;
66 b.push_str(&ws.render(left));
67 b.push_str(&line);
68 b.push_str(&ws.render(right));
69 }
70 }
71
72 if i < lines.clone().count() - 1 {
73 b.push('\n');
74 }
75 }
76 b
77}
78
79pub fn place_vertical(height: i32, pos: Position, strs: String, opts: &[WhiteSpaceType]) -> String {
80 let content_height = get_strs_height(&strs);
81 let gap = height as usize - content_height;
82 if gap <= 0 {
83 return strs;
84 }
85
86 let mut ws = WhiteSpace::new(opts);
87
88 let (_, width) = get_lines(&strs);
89 let empty_line = format!("{}\n", ws.render(width));
90
91 let mut b = String::new();
92 match pos {
93 Position::Bottom => {
94 b.push_str(&empty_line.repeat(gap));
95 b.push_str(&strs);
96 }
97 Position::Top => {
98 b.push_str(&strs);
99 for _ in 0..gap {
100 b.push('\n');
101 b.push_str(&empty_line);
102 }
103 }
104 _ => {
105 let top = gap / 2;
106 let bottom = gap / 2;
107 b.push_str(&empty_line.repeat(top));
108 b.push_str(&strs);
109 for _ in 0..bottom {
110 b.push('\n');
111 b.push_str(&empty_line);
112 }
113 }
114 }
115 b
116}