1 | //! This module contains a [`Rotate`] primitive which can be used in order to rotate [`Table`]. |
2 | //! |
3 | //! It's also possible to transpose the table at the point of construction. |
4 | //! See [`Builder::index`]. |
5 | //! |
6 | //! # Example |
7 | //! |
8 | #![cfg_attr (feature = "std" , doc = "```" )] |
9 | #![cfg_attr (not(feature = "std" ), doc = "```ignore" )] |
10 | //! use tabled::{Table, settings::Rotate}; |
11 | //! |
12 | //! let data = [[1, 2, 3], [4, 5, 6]]; |
13 | //! |
14 | //! let table = Table::new(data).with(Rotate::Left).to_string(); |
15 | //! |
16 | //! assert_eq!( |
17 | //! table, |
18 | //! concat!( |
19 | //! "+---+---+---+ \n" , |
20 | //! "| 2 | 3 | 6 | \n" , |
21 | //! "+---+---+---+ \n" , |
22 | //! "| 1 | 2 | 5 | \n" , |
23 | //! "+---+---+---+ \n" , |
24 | //! "| 0 | 1 | 4 | \n" , |
25 | //! "+---+---+---+" , |
26 | //! ) |
27 | //! ); |
28 | //! ``` |
29 | //! |
30 | //! [`Table`]: crate::Table |
31 | //! [`Builder::index`]: crate::builder::Builder::index |
32 | |
33 | // use core::cmp::max; |
34 | use core::cmp::max; |
35 | |
36 | use crate::{ |
37 | grid::records::{ExactRecords, Records, Resizable}, |
38 | settings::TableOption, |
39 | }; |
40 | |
41 | /// Rotate can be used to rotate a table by 90 degrees. |
42 | #[derive (Debug)] |
43 | pub enum Rotate { |
44 | /// Rotate [`Table`] to the left. |
45 | /// |
46 | /// [`Table`]: crate::Table |
47 | Left, |
48 | /// Rotate [`Table`] to the right. |
49 | /// |
50 | /// [`Table`]: crate::Table |
51 | Right, |
52 | /// Rotate [`Table`] to the top. |
53 | /// |
54 | /// So the top becomes the bottom. |
55 | /// |
56 | /// [`Table`]: crate::Table |
57 | Top, |
58 | /// Rotate [`Table`] to the bottom. |
59 | /// |
60 | /// So the top becomes the bottom. |
61 | /// |
62 | /// [`Table`]: crate::Table |
63 | Bottom, |
64 | } |
65 | |
66 | impl<R, D, C> TableOption<R, D, C> for Rotate |
67 | where |
68 | R: Records + ExactRecords + Resizable, |
69 | { |
70 | fn change(self, records: &mut R, _: &mut C, _: &mut D) { |
71 | let count_rows = records.count_rows(); |
72 | let count_cols = records.count_columns(); |
73 | |
74 | match self { |
75 | Self::Left => { |
76 | let size = max(count_rows, count_cols); |
77 | |
78 | { |
79 | for _ in count_rows..size { |
80 | records.push_row(); |
81 | } |
82 | |
83 | for _ in count_cols..size { |
84 | records.push_column(); |
85 | } |
86 | } |
87 | |
88 | for col in 0..size { |
89 | for row in col..size { |
90 | records.swap((col, row), (row, col)); |
91 | } |
92 | } |
93 | |
94 | for row in 0..count_cols / 2 { |
95 | records.swap_row(row, count_cols - row - 1); |
96 | } |
97 | |
98 | { |
99 | for (shift, row) in (count_rows..size).enumerate() { |
100 | let row = row - shift; |
101 | records.remove_column(row); |
102 | } |
103 | |
104 | for (shift, col) in (count_cols..size).enumerate() { |
105 | let col = col - shift; |
106 | records.remove_row(col); |
107 | } |
108 | } |
109 | } |
110 | Self::Right => { |
111 | let size = max(count_rows, count_cols); |
112 | |
113 | { |
114 | for _ in count_rows..size { |
115 | records.push_row(); |
116 | } |
117 | |
118 | for _ in count_cols..size { |
119 | records.push_column(); |
120 | } |
121 | } |
122 | |
123 | for col in 0..size { |
124 | for row in col..size { |
125 | records.swap((col, row), (row, col)); |
126 | } |
127 | } |
128 | |
129 | for col in 0..count_rows / 2 { |
130 | records.swap_column(col, count_rows - col - 1); |
131 | } |
132 | |
133 | { |
134 | for (shift, row) in (count_rows..size).enumerate() { |
135 | let row = row - shift; |
136 | records.remove_column(row); |
137 | } |
138 | |
139 | for (shift, col) in (count_cols..size).enumerate() { |
140 | let col = col - shift; |
141 | records.remove_row(col); |
142 | } |
143 | } |
144 | } |
145 | Self::Bottom | Self::Top => { |
146 | for row in 0..count_rows / 2 { |
147 | for col in 0..count_cols { |
148 | let last_row = count_rows - row - 1; |
149 | records.swap((last_row, col), (row, col)); |
150 | } |
151 | } |
152 | } |
153 | } |
154 | } |
155 | } |
156 | |