workspace: Add settings to dim inactive panes and highlight active pane (#18968)

Closes #12529
Closes #8639

Release Notes:

- Added option to dim inactive panes
([#12529](https://github.com/zed-industries/zed/issues/12529))
- Added option to highlight active pane with a border
([#8639](https://github.com/zed-industries/zed/issues/8639))

BREAKING: `active_pane_magnification` value is no longer used, it should
be migrated to `active_pane_modifiers.magnification`


![panes](https://github.com/user-attachments/assets/b19959bc-4c06-4320-be36-412113143af5)

> note: don't know much rust, so I wouldn't be surprised if stuff can be
done much better, happy to update things after the review.
Also, wasn't sure about introducing the new object in the settings, but
it felt better than adding two more keys to the root, let me know what
you think and if there's a better way to do this. Also happy to get
feedback on the text itself, as I didn't spend much thinking how to
document this.
This commit is contained in:
Alex Viscreanu 2024-11-05 16:26:07 +01:00 committed by GitHub
parent b8501199c2
commit bc3550d991
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 108 additions and 18 deletions

View file

@ -68,9 +68,17 @@
"ui_font_size": 16, "ui_font_size": 16,
// How much to fade out unused code. // How much to fade out unused code.
"unnecessary_code_fade": 0.3, "unnecessary_code_fade": 0.3,
// Active pane styling settings.
"active_pane_modifiers": {
// The factor to grow the active pane by. Defaults to 1.0 // The factor to grow the active pane by. Defaults to 1.0
// which gives the same size as all other panes. // which gives the same size as all other panes.
"active_pane_magnification": 1.0, "magnification": 1.0,
// Inset border size of the active pane, in pixels.
"border_size": 0.0,
// Opacity of the inactive panes. 0 means transparent, 1 means opaque.
// Values are clamped to the [0.0, 1.0] range.
"inactive_opacity": 1.0
},
// The direction that you want to split panes horizontally. Defaults to "up" // The direction that you want to split panes horizontally. Defaults to "up"
"pane_split_direction_horizontal": "up", "pane_split_direction_horizontal": "up",
// The direction that you want to split panes horizontally. Defaults to "left" // The direction that you want to split panes horizontally. Defaults to "left"

View file

@ -867,12 +867,10 @@ mod element {
debug_assert!(flexes.len() == len); debug_assert!(flexes.len() == len);
debug_assert!(flex_values_in_bounds(flexes.as_slice())); debug_assert!(flex_values_in_bounds(flexes.as_slice()));
let magnification_value = WorkspaceSettings::get(None, cx).active_pane_magnification; let active_pane_magnification = WorkspaceSettings::get(None, cx)
let active_pane_magnification = if magnification_value == 1. { .active_pane_modifiers
None .magnification
} else { .and_then(|val| if val == 1.0 { None } else { Some(val) });
Some(magnification_value)
};
let total_flex = if let Some(flex) = active_pane_magnification { let total_flex = if let Some(flex) = active_pane_magnification {
self.children.len() as f32 - 1. + flex self.children.len() as f32 - 1. + flex
@ -910,6 +908,7 @@ mod element {
origin, origin,
size: child_size, size: child_size,
}; };
bounding_boxes.push(Some(child_bounds)); bounding_boxes.push(Some(child_bounds));
child.layout_as_root(child_size.into(), cx); child.layout_as_root(child_size.into(), cx);
child.prepaint_at(origin, cx); child.prepaint_at(origin, cx);
@ -944,7 +943,54 @@ mod element {
child.element.paint(cx); child.element.paint(cx);
} }
let overlay_opacity = WorkspaceSettings::get(None, cx)
.active_pane_modifiers
.inactive_opacity
.map(|val| val.clamp(0.0, 1.0))
.and_then(|val| (val <= 1.).then_some(val));
let mut overlay_background = cx.theme().colors().editor_background;
if let Some(opacity) = overlay_opacity {
overlay_background.fade_out(opacity);
}
let overlay_border = WorkspaceSettings::get(None, cx)
.active_pane_modifiers
.border_size
.and_then(|val| (val >= 0.).then_some(val));
for (ix, child) in &mut layout.children.iter_mut().enumerate() { for (ix, child) in &mut layout.children.iter_mut().enumerate() {
if overlay_opacity.is_some() || overlay_border.is_some() {
// the overlay has to be painted in origin+1px with size width-1px
// in order to accommodate the divider between panels
let overlay_bounds = Bounds {
origin: child
.bounds
.origin
.apply_along(Axis::Horizontal, |val| val + Pixels(1.)),
size: child
.bounds
.size
.apply_along(Axis::Horizontal, |val| val - Pixels(1.)),
};
if overlay_opacity.is_some() && self.active_pane_ix != Some(ix) {
cx.paint_quad(gpui::fill(overlay_bounds, overlay_background));
}
if let Some(border) = overlay_border {
if self.active_pane_ix == Some(ix) {
cx.paint_quad(gpui::quad(
overlay_bounds,
0.,
gpui::transparent_black(),
border,
cx.theme().colors().border_selected,
));
}
}
}
if let Some(handle) = child.handle.as_mut() { if let Some(handle) = child.handle.as_mut() {
let cursor_style = match self.axis { let cursor_style = match self.axis {
Axis::Vertical => CursorStyle::ResizeRow, Axis::Vertical => CursorStyle::ResizeRow,

View file

@ -7,7 +7,7 @@ use settings::{Settings, SettingsSources};
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct WorkspaceSettings { pub struct WorkspaceSettings {
pub active_pane_magnification: f32, pub active_pane_modifiers: ActivePanelModifiers,
pub pane_split_direction_horizontal: PaneSplitDirectionHorizontal, pub pane_split_direction_horizontal: PaneSplitDirectionHorizontal,
pub pane_split_direction_vertical: PaneSplitDirectionVertical, pub pane_split_direction_vertical: PaneSplitDirectionVertical,
pub centered_layout: CenteredLayoutSettings, pub centered_layout: CenteredLayoutSettings,
@ -21,6 +21,30 @@ pub struct WorkspaceSettings {
pub command_aliases: HashMap<String, String>, pub command_aliases: HashMap<String, String>,
} }
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ActivePanelModifiers {
/// Scale by which to zoom the active pane.
/// When set to 1.0, the active pane has the same size as others,
/// but when set to a larger value, the active pane takes up more space.
///
/// Default: `1.0`
pub magnification: Option<f32>,
/// Size of the border surrounding the active pane.
/// When set to 0, the active pane doesn't have any border.
/// The border is drawn inset.
///
/// Default: `0.0`
pub border_size: Option<f32>,
/// Opacity of inactive panels.
/// When set to 1.0, the inactive panes have the same opacity as the active one.
/// If set to 0, the inactive panes content will not be visible at all.
/// Values are clamped to the [0.0, 1.0] range.
///
/// Default: `1.0`
pub inactive_opacity: Option<f32>,
}
#[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema)] #[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum CloseWindowWhenNoItems { pub enum CloseWindowWhenNoItems {
@ -57,12 +81,8 @@ pub enum RestoreOnStartupBehavior {
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
pub struct WorkspaceSettingsContent { pub struct WorkspaceSettingsContent {
/// Scale by which to zoom the active pane. /// Active pane styling settings.
/// When set to 1.0, the active pane has the same size as others, pub active_pane_modifiers: Option<ActivePanelModifiers>,
/// but when set to a larger value, the active pane takes up more space.
///
/// Default: `1.0`
pub active_pane_magnification: Option<f32>,
// Direction to split horizontally. // Direction to split horizontally.
// //
// Default: "up" // Default: "up"

View file

@ -29,10 +29,26 @@ Extensions that provide language servers may also provide default settings for t
# Settings # Settings
## Active Pane Magnification ## Active Pane Modifiers
Styling settings applied to the active pane.
### Magnification
- Description: Scale by which to zoom the active pane. When set to `1.0`, the active pane has the same size as others, but when set to a larger value, the active pane takes up more space. - Description: Scale by which to zoom the active pane. When set to `1.0`, the active pane has the same size as others, but when set to a larger value, the active pane takes up more space.
- Setting: `active_pane_magnification` - Setting: `magnification`
- Default: `1.0`
### Border size
- Description: Size of the border surrounding the active pane. When set to 0, the active pane doesn't have any border. The border is drawn inset.
- Setting: `border_size`
- Default: `0.0`
### Inactive Opacity
- Description: Opacity of inactive panels. When set to 1.0, the inactive panes have the same opacity as the active one. If set to 0, the inactive panes content will not be visible at all. Values are clamped to the [0.0, 1.0] range.
- Setting: `inactive_opacity`
- Default: `1.0` - Default: `1.0`
**Options** **Options**