11use crate :: {
2- Editor ,
2+ Editor , EditorEvent ,
33 actions:: {
44 AddSelectionAbove , AddSelectionBelow , DuplicateLineDown , SelectAll , SelectLargerSyntaxNode ,
55 SelectNext , SelectSmallerSyntaxNode ,
@@ -113,6 +113,7 @@ pub struct EditorSelectionControls {
113113 active_item : Option < Box < dyn ItemHandle > > ,
114114 handle : PopoverMenuHandle < ContextMenu > ,
115115 options : SelectionControlsMenuOptions ,
116+ active_editor_subscription : Option < Subscription > ,
116117 _settings_subscription : Subscription ,
117118}
118119
@@ -133,6 +134,7 @@ impl EditorSelectionControls {
133134 active_item : None ,
134135 handle : Default :: default ( ) ,
135136 options,
137+ active_editor_subscription : None ,
136138 _settings_subscription : settings_subscription,
137139 }
138140 }
@@ -153,6 +155,26 @@ impl EditorSelectionControls {
153155 ToolbarItemLocation :: Hidden
154156 }
155157 }
158+
159+ fn subscribe_to_active_editor ( & mut self , cx : & mut Context < Self > ) {
160+ self . active_editor_subscription . take ( ) ;
161+
162+ let Some ( editor) = self . active_editor ( ) else {
163+ return ;
164+ } ;
165+
166+ self . active_editor_subscription = Some ( cx. subscribe (
167+ & editor,
168+ |this, _editor, event : & EditorEvent , cx| {
169+ if matches ! ( event, EditorEvent :: SelectionMenuChanged ) {
170+ cx. emit ( ToolbarItemEvent :: ChangeLocation (
171+ this. toolbar_item_location ( cx) ,
172+ ) ) ;
173+ cx. notify ( ) ;
174+ }
175+ } ,
176+ ) ) ;
177+ }
156178}
157179
158180impl Render for EditorSelectionControls {
@@ -190,6 +212,69 @@ impl ToolbarItemView for EditorSelectionControls {
190212 cx : & mut Context < Self > ,
191213 ) -> ToolbarItemLocation {
192214 self . active_item = active_pane_item. map ( ItemHandle :: boxed_clone) ;
215+ self . subscribe_to_active_editor ( cx) ;
193216 self . toolbar_item_location ( cx)
194217 }
195218}
219+
220+ #[ cfg( test) ]
221+ mod tests {
222+ use super :: * ;
223+ use crate :: { actions:: ToggleSelectionMenu , test:: build_editor} ;
224+ use gpui:: TestAppContext ;
225+ use multi_buffer:: MultiBuffer ;
226+ use std:: { cell:: RefCell , rc:: Rc } ;
227+
228+ fn init_test ( cx : & mut TestAppContext ) {
229+ cx. update ( |cx| {
230+ assets:: Assets . load_test_fonts ( cx) ;
231+ let store = SettingsStore :: test ( cx) ;
232+ cx. set_global ( store) ;
233+ theme_settings:: init ( theme:: LoadThemes :: JustBase , cx) ;
234+ release_channel:: init ( semver:: Version :: new ( 0 , 0 , 0 ) , cx) ;
235+ crate :: init ( cx) ;
236+ } ) ;
237+ zlog:: init_test ( ) ;
238+ }
239+
240+ #[ gpui:: test]
241+ async fn selection_menu_toggle_updates_toolbar_location ( cx : & mut TestAppContext ) {
242+ init_test ( cx) ;
243+
244+ let ( editor, cx) = cx. add_window_view ( |window, cx| {
245+ let buffer = MultiBuffer :: build_simple ( "abc" , cx) ;
246+ build_editor ( buffer, window, cx)
247+ } ) ;
248+
249+ let events = Rc :: new ( RefCell :: new ( Vec :: new ( ) ) ) ;
250+ let controls = cx. new ( {
251+ let events = events. clone ( ) ;
252+ |cx| {
253+ cx. subscribe ( & cx. entity ( ) , move |_, _, event : & ToolbarItemEvent , _| {
254+ let ToolbarItemEvent :: ChangeLocation ( location) = event;
255+ events. borrow_mut ( ) . push ( * location) ;
256+ } )
257+ . detach ( ) ;
258+ EditorSelectionControls :: new ( cx)
259+ }
260+ } ) ;
261+
262+ controls. update_in ( cx, |controls, window, cx| {
263+ let active_item: & dyn ItemHandle = & editor;
264+ assert_eq ! (
265+ controls. set_active_pane_item( Some ( active_item) , window, cx) ,
266+ ToolbarItemLocation :: PrimaryRight
267+ ) ;
268+ } ) ;
269+
270+ editor. update_in ( cx, |editor, window, cx| {
271+ editor. toggle_selection_menu ( & ToggleSelectionMenu , window, cx) ;
272+ } ) ;
273+
274+ assert_eq ! (
275+ events. borrow( ) . as_slice( ) ,
276+ & [ ToolbarItemLocation :: Hidden ] ,
277+ "toggling the active editor's per-buffer selection menu must move the toolbar item"
278+ ) ;
279+ }
280+ }
0 commit comments