1010// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
1111// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
1212
13- mod tablist;
1413use std:: fmt:: Display ;
1514use std:: rc:: Rc ;
1615
1716use derivative:: Derivative ;
18- pub use tablist :: * ;
19- use yew:: { function_component , html, Callback , Component , Html , Properties } ;
17+ use itertools :: Itertools ;
18+ use yew:: { html, Callback , Component , Html , Properties } ;
2019
2120use super :: attributes_tab:: AttributesTabProps ;
2221use super :: style_tab:: StyleTabProps ;
22+ use crate :: components:: column_settings_sidebar:: attributes_tab:: AttributesTab ;
2323use crate :: components:: column_settings_sidebar:: save_settings:: SaveSettingsProps ;
24+ use crate :: components:: column_settings_sidebar:: style_tab:: StyleTab ;
2425use crate :: components:: containers:: sidebar:: Sidebar ;
25- use crate :: components:: editable_header:: EditableHeader ;
26+ use crate :: components:: containers:: tab_list:: { Tab , TabList } ;
27+ use crate :: components:: editable_header:: EditableHeaderProps ;
2628use crate :: components:: expression_editor:: ExpressionEditorProps ;
2729use crate :: components:: style:: LocalStyle ;
28- use crate :: components:: type_icon:: { TypeIcon , TypeIconType } ;
30+ use crate :: components:: type_icon:: TypeIconType ;
2931use crate :: components:: viewer:: ColumnLocator ;
3032use crate :: config:: { Expression , Type } ;
3133use crate :: custom_events:: CustomEvents ;
@@ -35,6 +37,13 @@ use crate::renderer::Renderer;
3537use crate :: session:: Session ;
3638use crate :: { css, derive_model, html_template} ;
3739
40+ #[ derive( Debug , Default , Clone , Copy , PartialEq ) ]
41+ pub enum ColumnSettingsTab {
42+ #[ default]
43+ Attributes ,
44+ Style ,
45+ }
46+ impl Tab for ColumnSettingsTab { }
3847impl Display for ColumnSettingsTab {
3948 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
4049 f. write_fmt ( format_args ! ( "{self:?}" ) )
@@ -87,14 +96,15 @@ pub struct ColumnSettingsSidebar {
8796 initial_header_value : Option < String > ,
8897 header_value : Option < String > ,
8998 header_valid : bool ,
90- selected_tab : ( usize , ColumnSettingsTab ) ,
99+ selected_tab : ColumnSettingsTab ,
100+ selected_tab_idx : usize ,
91101 save_enabled : bool ,
92102 save_count : u8 ,
93103 reset_enabled : bool ,
94104 reset_count : u8 ,
95105 column_name : String ,
96106 maybe_ty : Option < Type > ,
97- tabs : Rc < Vec < ColumnSettingsTab > > ,
107+ tabs : Vec < ColumnSettingsTab > ,
98108}
99109
100110impl ColumnSettingsSidebar {
@@ -165,7 +175,7 @@ impl Component for ColumnSettingsSidebar {
165175 if ctx. props ( ) . selected_column . is_expr ( ) {
166176 tabs. push ( ColumnSettingsTab :: Attributes ) ;
167177 }
168- Rc :: new ( tabs)
178+ tabs
169179 } ;
170180
171181 Self {
@@ -184,7 +194,15 @@ impl Component for ColumnSettingsSidebar {
184194 fn changed ( & mut self , ctx : & yew:: prelude:: Context < Self > , old_props : & Self :: Properties ) -> bool {
185195 tracing:: error!( "Changed! {old_props:?} -> {:?}" , ctx. props( ) ) ;
186196 if ctx. props ( ) != old_props {
197+ let selected_tab = self . selected_tab ;
187198 * self = Self :: create ( ctx) ;
199+ self . selected_tab = selected_tab;
200+ self . selected_tab_idx = self
201+ . tabs
202+ . iter ( )
203+ . find_position ( |tab| * * tab == selected_tab)
204+ . map ( |( idx, _val) | idx)
205+ . unwrap_or_default ( ) ;
188206 true
189207 } else {
190208 false
@@ -194,7 +212,6 @@ impl Component for ColumnSettingsSidebar {
194212 fn update ( & mut self , ctx : & yew:: prelude:: Context < Self > , msg : Self :: Message ) -> bool {
195213 tracing:: error!( "Updated! {msg:?}" ) ;
196214 match msg {
197- // is there a better pattern for this?
198215 ColumnSettingsMsg :: SetExprValue ( val) => {
199216 if self . expr_value != val {
200217 self . expr_value = val;
@@ -223,9 +240,10 @@ impl Component for ColumnSettingsSidebar {
223240 self . save_enabled_effect ( ) ;
224241 true
225242 } ,
226- ColumnSettingsMsg :: SetSelectedTab ( val) => {
227- let rerender = self . selected_tab != val;
243+ ColumnSettingsMsg :: SetSelectedTab ( ( idx , val) ) => {
244+ let rerender = self . selected_tab != val || self . selected_tab_idx != idx ;
228245 self . selected_tab = val;
246+ self . selected_tab_idx = idx;
229247 rerender
230248 } ,
231249 ColumnSettingsMsg :: OnResetAttributes ( ( ) ) => {
@@ -251,6 +269,8 @@ impl Component for ColumnSettingsSidebar {
251269 } ,
252270 }
253271
272+ self . initial_expr_value = self . expr_value . clone ( ) ;
273+ self . initial_header_value = self . header_value . clone ( ) ;
254274 self . save_enabled = false ;
255275 self . reset_enabled = false ;
256276 self . save_count += 1 ;
@@ -268,27 +288,24 @@ impl Component for ColumnSettingsSidebar {
268288
269289 fn view ( & self , ctx : & yew:: prelude:: Context < Self > ) -> Html {
270290 tracing:: error!( "Render!" ) ;
271- let editable = ctx. props ( ) . selected_column . is_expr ( )
272- && matches ! ( self . selected_tab. 1 , ColumnSettingsTab :: Attributes ) ;
273- let header_icon = html ! {
274- <TypeIcon ty={ self . maybe_ty. map( |ty| ty. into( ) ) . unwrap_or( TypeIconType :: Expr ) } />
275- } ;
276- let on_change = ctx. link ( ) . batch_callback ( |( value, valid) | {
277- vec ! [
278- ColumnSettingsMsg :: SetHeaderValue ( value) ,
279- ColumnSettingsMsg :: SetHeaderValid ( valid) ,
280- ]
281- } ) ;
282- let header_contents = html ! {
283- <EditableHeader
284- icon={ Some ( header_icon) }
285- { on_change}
286- { editable}
287- initial_value={ self . initial_header_value. clone( ) }
288- placeholder={ self . expr_value. clone( ) }
289- session={ ctx. props( ) . session. clone( ) }
290- reset_count={ self . reset_count}
291- />
291+
292+ let header_props = EditableHeaderProps {
293+ icon_type : self
294+ . maybe_ty
295+ . map ( |ty| ty. into ( ) )
296+ . or ( Some ( TypeIconType :: Expr ) ) ,
297+ on_change : ctx. link ( ) . batch_callback ( |( value, valid) | {
298+ vec ! [
299+ ColumnSettingsMsg :: SetHeaderValue ( value) ,
300+ ColumnSettingsMsg :: SetHeaderValid ( valid) ,
301+ ]
302+ } ) ,
303+ editable : ctx. props ( ) . selected_column . is_expr ( )
304+ && matches ! ( self . selected_tab, ColumnSettingsTab :: Attributes ) ,
305+ initial_value : self . initial_header_value . clone ( ) ,
306+ placeholder : self . expr_value . clone ( ) ,
307+ session : ctx. props ( ) . session . clone ( ) ,
308+ reset_count : self . reset_count ,
292309 } ;
293310
294311 let expr_editor = ExpressionEditorProps {
@@ -324,28 +341,26 @@ impl Component for ColumnSettingsSidebar {
324341 column_name : self . column_name . clone ( ) ,
325342 } ;
326343
344+ let tab_children = self . tabs . iter ( ) . map ( |tab| match tab {
345+ ColumnSettingsTab :: Attributes => html ! { <AttributesTab ..attrs_tab. clone( ) />} ,
346+ ColumnSettingsTab :: Style => html ! { <StyleTab ..style_tab. clone( ) />} ,
347+ } ) ;
348+
327349 html_template ! {
328350 <LocalStyle href={ css!( "column-settings-panel" ) } />
329351 <Sidebar
330352 on_close={ ctx. props( ) . on_close. clone( ) }
331353 id_prefix="column_settings"
332354 width_override={ ctx. props( ) . width_override}
333- selected_tab={ self . selected_tab . 0 }
334- { header_contents }
355+ selected_tab={ self . selected_tab_idx }
356+ { header_props }
335357 >
336- <ColumnSettingsTablist
337- renderer={ ctx. props( ) . renderer. clone( ) }
338- presentation={ ctx. props( ) . presentation. clone( ) }
339- session={ ctx. props( ) . session. clone( ) }
340- custom_events={ ctx. props( ) . custom_events. clone( ) }
341-
342- on_tab_change={ ctx. link( ) . callback( ColumnSettingsMsg :: SetSelectedTab ) }
343- selected_tab={ self . selected_tab}
358+ <TabList <ColumnSettingsTab >
344359 tabs={ self . tabs. clone( ) }
345-
346- { attrs_tab }
347- { style_tab }
348- / >
360+ on_tab_change= { ctx . link ( ) . callback ( ColumnSettingsMsg :: SetSelectedTab ) }
361+ selected_tab= { self . selected_tab_idx } >
362+ { for tab_children }
363+ </ TabList < ColumnSettingsTab > >
349364 </Sidebar >
350365 }
351366 }
0 commit comments