@@ -7,7 +7,8 @@ use buffer_diff::{BufferDiff, BufferDiffSnapshot};
77use collections:: HashMap ;
88
99use gpui:: {
10- Action , AppContext as _, Entity , EventEmitter , Focusable , Font , Subscription , WeakEntity ,
10+ Action , AppContext as _, Entity , EventEmitter , Focusable , Font , Pixels , Subscription ,
11+ WeakEntity , canvas,
1112} ;
1213use itertools:: Itertools ;
1314use language:: { Buffer , Capability , HighlightedText } ;
@@ -17,7 +18,7 @@ use multi_buffer::{
1718} ;
1819use project:: Project ;
1920use rope:: Point ;
20- use settings:: DiffViewStyle ;
21+ use settings:: { DiffViewStyle , Settings } ;
2122use text:: { Bias , BufferId , OffsetRangeExt as _, Patch , ToPoint as _} ;
2223use ui:: {
2324 App , Context , InteractiveElement as _, IntoElement as _, ParentElement as _, Render ,
@@ -36,7 +37,7 @@ use workspace::{
3637} ;
3738
3839use crate :: {
39- Autoscroll , Editor , EditorEvent , RenderDiffHunkControlsFn , ToggleSoftWrap ,
40+ Autoscroll , Editor , EditorEvent , EditorSettings , RenderDiffHunkControlsFn , ToggleSoftWrap ,
4041 actions:: { DisableBreakpoint , EditLogBreakpoint , EnableBreakpoint , ToggleBreakpoint } ,
4142 display_map:: Companion ,
4243} ;
@@ -377,6 +378,12 @@ pub struct SplittableEditor {
377378 workspace : WeakEntity < Workspace > ,
378379 split_state : Entity < SplitEditorState > ,
379380 searched_side : Option < SplitSide > ,
381+ /// The preferred diff style.
382+ diff_view_style : DiffViewStyle ,
383+ /// True when the current width is below the minimum threshold for split
384+ /// mode, regardless of the current diff view style setting.
385+ too_narrow_for_split : bool ,
386+ last_width : Option < Pixels > ,
380387 _subscriptions : Vec < Subscription > ,
381388}
382389
@@ -396,6 +403,10 @@ impl SplittableEditor {
396403 self . lhs . as_ref ( ) . map ( |s| & s. editor )
397404 }
398405
406+ pub fn diff_view_style ( & self ) -> DiffViewStyle {
407+ self . diff_view_style
408+ }
409+
399410 pub fn is_split ( & self ) -> bool {
400411 self . lhs . is_some ( )
401412 }
@@ -499,12 +510,15 @@ impl SplittableEditor {
499510 } ) ;
500511 let split_state = cx. new ( |cx| SplitEditorState :: new ( cx) ) ;
501512 Self {
513+ diff_view_style : style,
502514 rhs_editor,
503515 rhs_multibuffer,
504516 lhs : None ,
505517 workspace : workspace. downgrade ( ) ,
506518 split_state,
507519 searched_side : None ,
520+ too_narrow_for_split : false ,
521+ last_width : None ,
508522 _subscriptions : subscriptions,
509523 }
510524 }
@@ -826,10 +840,19 @@ impl SplittableEditor {
826840 window : & mut Window ,
827841 cx : & mut Context < Self > ,
828842 ) {
829- if self . lhs . is_some ( ) {
830- self . unsplit ( window, cx) ;
831- } else {
832- self . split ( window, cx) ;
843+ match self . diff_view_style {
844+ DiffViewStyle :: Unified => {
845+ self . diff_view_style = DiffViewStyle :: Split ;
846+ if !self . too_narrow_for_split {
847+ self . split ( window, cx) ;
848+ }
849+ }
850+ DiffViewStyle :: Split => {
851+ self . diff_view_style = DiffViewStyle :: Unified ;
852+ if self . is_split ( ) {
853+ self . unsplit ( window, cx) ;
854+ }
855+ }
833856 }
834857 }
835858
@@ -1249,6 +1272,35 @@ impl SplittableEditor {
12491272 }
12501273 } ) ;
12511274 }
1275+
1276+ fn width_changed ( & mut self , width : Pixels , window : & mut Window , cx : & mut Context < Self > ) {
1277+ self . last_width = Some ( width) ;
1278+
1279+ let min_ems = EditorSettings :: get_global ( cx) . minimum_split_diff_width ;
1280+
1281+ let style = self . rhs_editor . read ( cx) . create_style ( cx) ;
1282+ let font_id = window. text_system ( ) . resolve_font ( & style. text . font ( ) ) ;
1283+ let font_size = style. text . font_size . to_pixels ( window. rem_size ( ) ) ;
1284+ let em_advance = window
1285+ . text_system ( )
1286+ . em_advance ( font_id, font_size)
1287+ . unwrap_or ( font_size) ;
1288+ let min_width = em_advance * min_ems;
1289+ let is_split = self . lhs . is_some ( ) ;
1290+
1291+ self . too_narrow_for_split = min_ems > 0.0 && width < min_width;
1292+
1293+ match self . diff_view_style {
1294+ DiffViewStyle :: Unified => { }
1295+ DiffViewStyle :: Split => {
1296+ if self . too_narrow_for_split && is_split {
1297+ self . unsplit ( window, cx) ;
1298+ } else if !self . too_narrow_for_split && !is_split {
1299+ self . split ( window, cx) ;
1300+ }
1301+ }
1302+ }
1303+ }
12521304}
12531305
12541306#[ cfg( test) ]
@@ -2042,30 +2094,23 @@ impl Focusable for SplittableEditor {
20422094 }
20432095}
20442096
2045- // impl Item for SplittableEditor {
2046- // type Event = EditorEvent;
2047-
2048- // fn tab_content_text(&self, detail: usize, cx: &App) -> ui::SharedString {
2049- // self.rhs_editor().tab_content_text(detail, cx)
2050- // }
2051-
2052- // fn as_searchable(&self, _this: &Entity<Self>, cx: &App) -> Option<Box<dyn workspace::searchable::SearchableItemHandle>> {
2053- // Some(Box::new(self.last_selected_editor().clone()))
2054- // }
2055- // }
2056-
20572097impl Render for SplittableEditor {
20582098 fn render (
20592099 & mut self ,
20602100 _window : & mut ui:: Window ,
20612101 cx : & mut ui:: Context < Self > ,
20622102 ) -> impl ui:: IntoElement {
2063- let inner = if self . lhs . is_some ( ) {
2103+ let is_split = self . lhs . is_some ( ) ;
2104+ let inner = if is_split {
20642105 let style = self . rhs_editor . read ( cx) . create_style ( cx) ;
20652106 SplitEditorView :: new ( cx. entity ( ) , style, self . split_state . clone ( ) ) . into_any_element ( )
20662107 } else {
20672108 self . rhs_editor . clone ( ) . into_any_element ( )
20682109 } ;
2110+
2111+ let this = cx. entity ( ) . downgrade ( ) ;
2112+ let last_width = self . last_width ;
2113+
20692114 div ( )
20702115 . id ( "splittable-editor" )
20712116 . on_action ( cx. listener ( Self :: toggle_split) )
@@ -2079,6 +2124,25 @@ impl Render for SplittableEditor {
20792124 . capture_action ( cx. listener ( Self :: toggle_soft_wrap) )
20802125 . size_full ( )
20812126 . child ( inner)
2127+ . child (
2128+ canvas (
2129+ move |bounds, window, cx| {
2130+ let width = bounds. size . width ;
2131+ if last_width == Some ( width) {
2132+ return ;
2133+ }
2134+ window. defer ( cx, move |window, cx| {
2135+ this. update ( cx, |this, cx| {
2136+ this. width_changed ( width, window, cx) ;
2137+ } )
2138+ . ok ( ) ;
2139+ } ) ;
2140+ } ,
2141+ |_, _, _, _| { } ,
2142+ )
2143+ . absolute ( )
2144+ . size_full ( ) ,
2145+ )
20822146 }
20832147}
20842148
0 commit comments