@@ -10,31 +10,86 @@ use ratatui::{prelude::*, widgets::*};
10
10
use serde:: { Deserialize , Serialize } ;
11
11
use tokio:: sync:: mpsc:: UnboundedSender ;
12
12
13
- use super :: { Component , Frame } ;
13
+ use super :: Frame ;
14
14
use crate :: {
15
15
action:: Action ,
16
16
app:: { App , AppState } ,
17
- components:: scrollable:: { ScrollDirection , Scrollable } ,
17
+ components:: {
18
+ scrollable:: { ScrollDirection , Scrollable } ,
19
+ Component ,
20
+ } ,
18
21
config:: { Config , KeyBindings } ,
19
22
database:: { get_headers, parse_value, row_to_json, row_to_vec, DbError , Rows } ,
20
23
focus:: Focus ,
21
24
tui:: Event ,
22
25
} ;
23
26
27
+ pub enum DataState {
28
+ NoResults ,
29
+ Blank ,
30
+ HasResults ,
31
+ Error ( DbError ) ,
32
+ }
33
+
34
+ pub trait SettableDataTable < ' a > {
35
+ fn set_data_state ( & mut self , data : Option < Result < Rows , DbError > > ) ;
36
+ }
37
+
38
+ pub trait DataComponent < ' a > : Component + SettableDataTable < ' a > { }
39
+ impl < ' a , T > DataComponent < ' a > for T where T : Component + SettableDataTable < ' a >
40
+ {
41
+ }
42
+
24
43
pub struct Data < ' a > {
25
44
command_tx : Option < UnboundedSender < Action > > ,
26
45
config : Config ,
27
46
scrollable : Scrollable < ' a > ,
47
+ data_state : DataState ,
28
48
state : Arc < Mutex < AppState > > ,
29
49
}
30
50
31
51
impl < ' a > Data < ' a > {
32
52
pub fn new ( state : Arc < Mutex < AppState > > ) -> Self {
33
- Data { command_tx : None , config : Config :: default ( ) , scrollable : Scrollable :: default ( ) , state }
53
+ Data {
54
+ command_tx : None ,
55
+ config : Config :: default ( ) ,
56
+ scrollable : Scrollable :: default ( ) ,
57
+ data_state : DataState :: Blank ,
58
+ state,
59
+ }
34
60
}
61
+ }
35
62
36
- pub fn set_data ( ) {
37
- // TODO
63
+ impl < ' a > SettableDataTable < ' a > for Data < ' a > {
64
+ fn set_data_state ( & mut self , data : Option < Result < Rows , DbError > > ) {
65
+ match data {
66
+ Some ( Ok ( rows) ) => {
67
+ if rows. is_empty ( ) {
68
+ self . data_state = DataState :: NoResults ;
69
+ } else {
70
+ let headers = get_headers ( & rows) ;
71
+ let header_row =
72
+ Row :: new ( headers. iter ( ) . map ( |h| Cell :: from ( format ! ( "{}\n {}" , h. name, h. type_name) ) ) . collect :: < Vec < Cell > > ( ) )
73
+ . height ( 2 )
74
+ . bottom_margin ( 1 ) ;
75
+ let value_rows = rows. iter ( ) . map ( |r| Row :: new ( row_to_vec ( r) ) . bottom_margin ( 1 ) ) . collect :: < Vec < Row > > ( ) ;
76
+ let buf_table =
77
+ Table :: default ( ) . rows ( value_rows) . header ( header_row) . style ( Style :: default ( ) ) . column_spacing ( 1 ) ;
78
+ self . scrollable . child (
79
+ Box :: new ( buf_table) ,
80
+ 16_u16 . saturating_mul ( headers. len ( ) as u16 ) ,
81
+ 4_u16 . saturating_mul ( rows. len ( ) as u16 ) ,
82
+ ) ;
83
+ self . data_state = DataState :: HasResults ;
84
+ }
85
+ } ,
86
+ Some ( Err ( e) ) => {
87
+ self . data_state = DataState :: Error ( e) ;
88
+ } ,
89
+ _ => {
90
+ self . data_state = DataState :: Blank ;
91
+ } ,
92
+ }
38
93
}
39
94
}
40
95
@@ -94,34 +149,58 @@ impl<'a> Component for Data<'a> {
94
149
Style :: new ( ) . dim ( )
95
150
} ) ;
96
151
97
- match & state. data {
98
- Some ( Ok ( rows) ) => ' rows: {
99
- if rows. is_empty ( ) {
100
- f. render_widget ( Paragraph :: new ( "no results" ) . wrap ( Wrap { trim : false } ) . block ( block) , area) ;
101
- break ' rows;
102
- }
103
- let headers = get_headers ( rows) ;
104
- let header_row =
105
- Row :: new ( headers. iter ( ) . map ( |h| Cell :: from ( format ! ( "{}\n {}" , h. name, h. type_name) ) ) . collect :: < Vec < Cell > > ( ) )
106
- . height ( 2 )
107
- . bottom_margin ( 1 ) ;
108
- let value_rows = rows. iter ( ) . map ( |r| Row :: new ( row_to_vec ( r) ) . bottom_margin ( 1 ) ) . collect :: < Vec < Row > > ( ) ;
109
- let buf_table = Table :: default ( ) . rows ( value_rows) . header ( header_row) . style ( Style :: default ( ) ) . column_spacing ( 1 ) ;
110
- self . scrollable . child ( Box :: new ( buf_table) , 100 , 250 ) . block ( block) ;
111
-
152
+ match & self . data_state {
153
+ DataState :: NoResults => {
154
+ f. render_widget ( Paragraph :: new ( "no results" ) . wrap ( Wrap { trim : false } ) . block ( block) , area) ;
155
+ } ,
156
+ DataState :: Blank => {
157
+ f. render_widget ( Paragraph :: new ( "" ) . wrap ( Wrap { trim : false } ) . block ( block) , area) ;
158
+ } ,
159
+ DataState :: HasResults => {
112
160
if !state. table_buf_logged {
113
161
self . scrollable . log ( ) ;
114
162
state. table_buf_logged = true ;
115
163
}
116
-
117
- self . scrollable . draw ( f, area) . unwrap ( ) ;
164
+ self . scrollable . block ( block ) ;
165
+ self . scrollable . draw ( f, area) ? ;
118
166
} ,
119
- Some ( Err ( e ) ) => {
120
- f. render_widget ( Paragraph :: new ( format ! ( "{:?}" , e. to_string( ) ) ) . wrap ( Wrap { trim : false } ) . block ( block) , area)
167
+ DataState :: Error ( e ) => {
168
+ f. render_widget ( Paragraph :: new ( format ! ( "{:?}" , e. to_string( ) ) ) . wrap ( Wrap { trim : false } ) . block ( block) , area) ;
121
169
} ,
122
- _ => f. render_widget ( Paragraph :: new ( "" ) . wrap ( Wrap { trim : false } ) . block ( block) , area) ,
123
170
}
124
171
125
172
Ok ( ( ) )
126
173
}
127
174
}
175
+
176
+ // // TODO: see if this trait can be fixed and used
177
+ //
178
+ // // based on: https://users.rust-lang.org/t/casting-traitobject-to-super-trait/33524/9
179
+ // pub trait IntoComponent<'a, Super: ?Sized> {
180
+ // fn as_super(&self) -> &Super;
181
+ // fn as_super_mut(&mut self) -> &mut Super;
182
+ // fn into_super(self: Box<Self>) -> Box<Super>;
183
+ // fn into_super_ref_mut(self: &'a mut Box<Self>) -> &'a mut Box<Super>;
184
+ // }
185
+ //
186
+ // impl<'a, T: 'a + Component> IntoComponent<'a, dyn Component + 'a> for T
187
+ // where
188
+ // T: Component + 'a,
189
+ // {
190
+ // fn as_super(&self) -> &(dyn Component + 'a) {
191
+ // self
192
+ // }
193
+ //
194
+ // fn as_super_mut(&mut self) -> &mut (dyn Component + 'a) {
195
+ // self
196
+ // }
197
+ //
198
+ // fn into_super(self: Box<Self>) -> Box<dyn Component + 'a> {
199
+ // self
200
+ // }
201
+ //
202
+ // fn into_super_ref_mut(self: &'a mut Box<Self>) -> &'a mut Box<dyn Component + 'a> {
203
+ // self
204
+ // }
205
+ // }
206
+ //
0 commit comments