@@ -12,14 +12,65 @@ use gpui_component::{
1212 h_flex,
1313 label:: Label ,
1414 list:: ListItem ,
15- tree:: { TreeItem , TreeState , tree} ,
15+ tree:: { TreeDelegate , TreeEntry , TreeItem , TreeState , tree} ,
1616 v_flex,
1717} ;
1818
1919use crate :: { Story , section} ;
2020
2121actions ! ( story, [ Rename , SelectItem ] ) ;
2222
23+ struct FileTreeDelegate {
24+ parent : Entity < TreeStory > ,
25+ }
26+
27+ impl TreeDelegate for FileTreeDelegate {
28+ fn render_item (
29+ & self ,
30+ ix : usize ,
31+ entry : & TreeEntry ,
32+ selected : bool ,
33+ window : & mut Window ,
34+ cx : & mut App ,
35+ ) -> ListItem {
36+ let item = entry. item ( ) ;
37+ let icon = if !entry. is_folder ( ) {
38+ IconName :: File
39+ } else if entry. is_expanded ( ) {
40+ IconName :: FolderOpen
41+ } else {
42+ IconName :: Folder
43+ } ;
44+
45+ ListItem :: new ( ix)
46+ . w_full ( )
47+ . rounded ( cx. theme ( ) . radius )
48+ . px_3 ( )
49+ . pl ( px ( 16. ) * entry. depth ( ) + px ( 12. ) )
50+ . child ( h_flex ( ) . gap_2 ( ) . child ( icon) . child ( item. label . clone ( ) ) )
51+ . selected ( selected)
52+ . on_click ( window. listener_for ( & self . parent , {
53+ let item = item. clone ( ) ;
54+ move |this, _, _window, cx| {
55+ this. selected_item = Some ( item. clone ( ) ) ;
56+ cx. notify ( ) ;
57+ }
58+ } ) )
59+ }
60+
61+ fn context_menu (
62+ & self ,
63+ ix : usize ,
64+ menu : gpui_component:: menu:: PopupMenu ,
65+ _window : & mut Window ,
66+ _cx : & mut App ,
67+ ) -> gpui_component:: menu:: PopupMenu {
68+ menu. label ( format ! ( "Selected Index: {}" , ix) )
69+ . separator ( )
70+ . menu ( "Rename" , Box :: new ( Rename ) )
71+ }
72+ }
73+
2374const CONTEXT : & str = "TreeStory" ;
2475pub ( crate ) fn init ( cx : & mut App ) {
2576 cx. bind_keys ( [
@@ -29,7 +80,7 @@ pub(crate) fn init(cx: &mut App) {
2980}
3081
3182pub struct TreeStory {
32- tree_state : Entity < TreeState > ,
83+ tree_state : Entity < TreeState < FileTreeDelegate > > ,
3384 selected_item : Option < TreeItem > ,
3485}
3586
@@ -71,7 +122,7 @@ impl TreeStory {
71122 cx. new ( |cx| Self :: new ( window, cx) )
72123 }
73124
74- fn load_files ( state : Entity < TreeState > , path : PathBuf , cx : & mut App ) {
125+ fn load_files ( state : Entity < TreeState < FileTreeDelegate > > , path : PathBuf , cx : & mut App ) {
75126 cx. spawn ( async move |cx| {
76127 let ignorer = Ignorer :: new ( & path. to_string_lossy ( ) ) ;
77128 let items = build_file_items ( & ignorer, & path, & path) ;
@@ -83,7 +134,15 @@ impl TreeStory {
83134 }
84135
85136 fn new ( _: & mut Window , cx : & mut Context < Self > ) -> Self {
86- let tree_state = cx. new ( |cx| TreeState :: new ( cx) ) ;
137+ let parent_entity = cx. entity ( ) ;
138+ let tree_state = cx. new ( move |cx| {
139+ TreeState :: new (
140+ FileTreeDelegate {
141+ parent : parent_entity,
142+ } ,
143+ cx,
144+ )
145+ } ) ;
87146
88147 Self :: load_files ( tree_state. clone ( ) , PathBuf :: from ( "./" ) , cx) ;
89148
@@ -134,7 +193,6 @@ impl Render for TreeStory {
134193 _: & mut gpui:: Window ,
135194 cx : & mut gpui:: Context < Self > ,
136195 ) -> impl gpui:: IntoElement {
137- let view = cx. entity ( ) ;
138196 v_flex ( )
139197 . id ( "tree-story" )
140198 . key_context ( CONTEXT )
@@ -144,46 +202,18 @@ impl Render for TreeStory {
144202 . size_full ( )
145203 . child (
146204 section ( "File tree" )
147- . sub_title ( "Press `space` to select, `enter` to rename." )
205+ . sub_title (
206+ "Press `space` to select, `enter` to rename, right-click for context menu." ,
207+ )
148208 . v_flex ( )
149209 . max_w_md ( )
150210 . child (
151- tree (
152- & self . tree_state ,
153- move |ix, entry, _selected, _window, cx| {
154- view. update ( cx, |_, cx| {
155- let item = entry. item ( ) ;
156- let icon = if !entry. is_folder ( ) {
157- IconName :: File
158- } else if entry. is_expanded ( ) {
159- IconName :: FolderOpen
160- } else {
161- IconName :: Folder
162- } ;
163-
164- ListItem :: new ( ix)
165- . w_full ( )
166- . rounded ( cx. theme ( ) . radius )
167- . px_3 ( )
168- . pl ( px ( 16. ) * entry. depth ( ) + px ( 12. ) )
169- . child (
170- h_flex ( ) . gap_2 ( ) . child ( icon) . child ( item. label . clone ( ) ) ,
171- )
172- . on_click ( cx. listener ( {
173- let item = item. clone ( ) ;
174- move |this, _, _window, cx| {
175- this. selected_item = Some ( item. clone ( ) ) ;
176- cx. notify ( ) ;
177- }
178- } ) )
179- } )
180- } ,
181- )
182- . p_1 ( )
183- . border_1 ( )
184- . border_color ( cx. theme ( ) . border )
185- . rounded ( cx. theme ( ) . radius )
186- . h ( px ( 540. ) ) ,
211+ tree ( & self . tree_state )
212+ . p_1 ( )
213+ . border_1 ( )
214+ . border_color ( cx. theme ( ) . border )
215+ . rounded ( cx. theme ( ) . radius )
216+ . h ( px ( 540. ) ) ,
187217 )
188218 . child (
189219 h_flex ( )
0 commit comments