Vertically align root folder in project panel with tabs and sidebar icons

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld
2021-09-30 13:30:24 -07:00
co-authored by Nathan Sobo
parent 177306d494
commit 5fb112ac4c
6 changed files with 72 additions and 64 deletions
+27 -5
View File
@@ -43,6 +43,8 @@ where
state: UniformListState,
item_count: usize,
append_items: F,
padding_top: f32,
padding_bottom: f32,
}
impl<F> UniformList<F>
@@ -54,9 +56,21 @@ where
state,
item_count,
append_items,
padding_top: 0.,
padding_bottom: 0.,
}
}
pub fn with_padding_top(mut self, padding: f32) -> Self {
self.padding_top = padding;
self
}
pub fn with_padding_bottom(mut self, padding: f32) -> Self {
self.padding_bottom = padding;
self
}
fn scroll(
&self,
_: Vector2F,
@@ -84,7 +98,7 @@ where
}
if let Some(item_ix) = state.scroll_to.take() {
let item_top = item_ix as f32 * item_height;
let item_top = self.padding_top + item_ix as f32 * item_height;
let item_bottom = item_top + item_height;
if item_top < state.scroll_top {
@@ -137,11 +151,16 @@ where
size.set_y(size.y().min(scroll_height).max(constraint.min.y()));
}
scroll_max = (item_height * self.item_count as f32 - size.y()).max(0.);
let scroll_height =
item_height * self.item_count as f32 + self.padding_top + self.padding_bottom;
scroll_max = (scroll_height - size.y()).max(0.);
self.autoscroll(scroll_max, size.y(), item_height);
items.clear();
let start = cmp::min((self.scroll_top() / item_height) as usize, self.item_count);
let start = cmp::min(
((self.scroll_top() - self.padding_top) / item_height) as usize,
self.item_count,
);
let end = cmp::min(
self.item_count,
start + (size.y() / item_height).ceil() as usize + 1,
@@ -173,8 +192,11 @@ where
) -> Self::PaintState {
cx.scene.push_layer(Some(bounds));
let mut item_origin =
bounds.origin() - vec2f(0.0, self.state.scroll_top() % layout.item_height);
let mut item_origin = bounds.origin()
- vec2f(
0.,
(self.state.scroll_top() - self.padding_top) % layout.item_height,
);
for item in &mut layout.items {
item.paint(item_origin, visible_bounds, cx);
+13 -11
View File
@@ -18,6 +18,7 @@ padding = { right = 4 }
width = 16
[workspace.tab]
height = 34
text = "$text.2"
padding = { left = 12, right = 12 }
icon_width = 8
@@ -26,10 +27,11 @@ icon_close = "$text.2.color"
icon_close_active = "$text.0.color"
icon_dirty = "$status.info"
icon_conflict = "$status.warn"
border = { left = true, bottom = true, width = 1, color = "$border.0" }
border = { left = true, bottom = true, width = 1, color = "$border.0", overlay = true }
[workspace.active_tab]
extends = "$workspace.tab"
border.bottom = false
background = "$surface.1"
text = "$text.0"
@@ -41,13 +43,14 @@ border = { right = true, width = 1, color = "$border.0" }
padding = { left = 1 }
background = "$border.0"
[workspace.sidebar.icon]
color = "$text.2.color"
height = 18
[workspace.sidebar.item]
icon_color = "$text.2.color"
icon_size = 18
height = "$workspace.tab.height"
[workspace.sidebar.active_icon]
extends = "$workspace.sidebar.icon"
color = "$text.0.color"
[workspace.sidebar.active_item]
extends = "$workspace.sidebar.item"
icon_color = "$text.0.color"
[workspace.left_sidebar]
extends = "$workspace.sidebar"
@@ -58,7 +61,7 @@ extends = "$workspace.sidebar"
border = { width = 1, color = "$border.0", left = true }
[panel]
padding = 12
padding = { top = 12, left = 12, bottom = 12, right = 12 }
[chat_panel]
extends = "$panel"
@@ -161,12 +164,11 @@ corner_radius = 6
[project_panel]
extends = "$panel"
padding = 0
entry_base_padding = "$panel.padding"
padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
[project_panel.entry]
text = "$text.1"
padding = { top = 3, bottom = 3 }
height = 22
icon_color = "$text.3.color"
icon_size = 8
icon_spacing = 8
+10 -2
View File
@@ -507,11 +507,15 @@ impl ProjectPanel {
Label::new(details.filename, style.text.clone())
.contained()
.with_margin_left(style.icon_spacing)
.aligned()
.left()
.boxed(),
)
.constrained()
.with_height(theme.entry.height)
.contained()
.with_style(style.container)
.with_padding_left(theme.entry_base_padding + details.depth as f32 * 20.)
.with_padding_left(theme.container.padding.left + details.depth as f32 * 20.)
.boxed()
},
)
@@ -534,6 +538,8 @@ impl View for ProjectPanel {
fn render(&mut self, _: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox {
let settings = self.settings.clone();
let mut container_style = settings.borrow().theme.project_panel.container;
let padding = std::mem::take(&mut container_style.padding);
let handle = self.handle.clone();
UniformList::new(
self.list.clone(),
@@ -551,8 +557,10 @@ impl View for ProjectPanel {
})
},
)
.with_padding_top(padding.top)
.with_padding_bottom(padding.bottom)
.contained()
.with_style(self.settings.borrow().theme.project_panel.container)
.with_style(container_style)
.boxed()
}
+9 -7
View File
@@ -67,6 +67,7 @@ pub struct OfflineIcon {
#[derive(Clone, Deserialize)]
pub struct Tab {
pub height: f32,
#[serde(flatten)]
pub container: ContainerStyle,
#[serde(flatten)]
@@ -84,14 +85,15 @@ pub struct Sidebar {
#[serde(flatten)]
pub container: ContainerStyle,
pub width: f32,
pub icon: SidebarIcon,
pub active_icon: SidebarIcon,
pub item: SidebarItem,
pub active_item: SidebarItem,
pub resize_handle: ContainerStyle,
}
#[derive(Deserialize)]
pub struct SidebarIcon {
pub color: Color,
pub struct SidebarItem {
pub icon_color: Color,
pub icon_size: f32,
pub height: f32,
}
@@ -107,18 +109,18 @@ pub struct ChatPanel {
pub hovered_sign_in_prompt: TextStyle,
}
#[derive(Deserialize)]
#[derive(Debug, Deserialize)]
pub struct ProjectPanel {
#[serde(flatten)]
pub container: ContainerStyle,
pub entry_base_padding: f32,
pub entry: ProjectPanelEntry,
pub hovered_entry: ProjectPanelEntry,
pub selected_entry: ProjectPanelEntry,
}
#[derive(Deserialize)]
#[derive(Debug, Deserialize)]
pub struct ProjectPanelEntry {
pub height: f32,
#[serde(flatten)]
pub container: ContainerStyle,
pub text: TextStyle,
+8 -29
View File
@@ -2,12 +2,11 @@ use super::{ItemViewHandle, SplitDirection};
use crate::settings::Settings;
use gpui::{
action,
color::Color,
elements::*,
geometry::{rect::RectF, vector::vec2f},
keymap::Binding,
platform::CursorStyle,
Border, Entity, MutableAppContext, Quad, RenderContext, View, ViewContext, ViewHandle,
Entity, MutableAppContext, Quad, RenderContext, View, ViewContext, ViewHandle,
};
use postage::watch;
use std::{cmp, path::Path, sync::Arc};
@@ -180,10 +179,6 @@ impl Pane {
fn render_tabs(&self, cx: &mut RenderContext<Self>) -> ElementBox {
let settings = self.settings.borrow();
let theme = &settings.theme;
let line_height = cx.font_cache().line_height(
theme.workspace.tab.label.text.font_id,
theme.workspace.tab.label.text.font_size,
);
enum Tabs {}
let tabs = MouseEventHandler::new::<Tabs, _, _, _>(0, cx, |mouse_state, cx| {
@@ -202,12 +197,11 @@ impl Pane {
title.push('…');
}
let mut style = theme.workspace.tab.clone();
if is_active {
style = theme.workspace.active_tab.clone();
style.container.border.bottom = false;
style.container.padding.bottom += style.container.border.width;
}
let mut style = if is_active {
theme.workspace.active_tab.clone()
} else {
theme.workspace.tab.clone()
};
if ix == 0 {
style.container.border.left = false;
}
@@ -319,26 +313,11 @@ impl Pane {
})
}
// Ensure there's always a minimum amount of space after the last tab,
// so that the tab's border doesn't abut the window's border.
let mut border = Border::bottom(1.0, Color::default());
border.color = theme.workspace.tab.container.border.color;
row.add_child(
ConstrainedBox::new(
Container::new(Empty::new().boxed())
.with_border(border)
.boxed(),
)
.with_min_width(20.)
.named("fixed-filler"),
);
row.add_child(
Expanded::new(
0.0,
Container::new(Empty::new().boxed())
.with_border(border)
.with_border(theme.workspace.tab.container.border)
.boxed(),
)
.named("filler"),
@@ -348,7 +327,7 @@ impl Pane {
});
ConstrainedBox::new(tabs.boxed())
.with_height(line_height + 16.)
.with_height(theme.workspace.tab.height)
.named("tabs")
}
}
+5 -10
View File
@@ -68,11 +68,6 @@ impl Sidebar {
pub fn render(&self, settings: &Settings, cx: &mut RenderContext<Workspace>) -> ElementBox {
let side = self.side;
let theme = &settings.theme;
let line_height = cx.font_cache().line_height(
theme.workspace.tab.label.text.font_id,
theme.workspace.tab.label.text.font_size,
);
let theme = self.theme(settings);
ConstrainedBox::new(
@@ -80,9 +75,9 @@ impl Sidebar {
Flex::column()
.with_children(self.items.iter().enumerate().map(|(item_index, item)| {
let theme = if Some(item_index) == self.active_item_ix {
&theme.active_icon
&theme.active_item
} else {
&theme.icon
&theme.item
};
enum SidebarButton {}
MouseEventHandler::new::<SidebarButton, _, _, _>(
@@ -93,15 +88,15 @@ impl Sidebar {
Align::new(
ConstrainedBox::new(
Svg::new(item.icon_path)
.with_color(theme.color)
.with_color(theme.icon_color)
.boxed(),
)
.with_height(theme.height)
.with_height(theme.icon_size)
.boxed(),
)
.boxed(),
)
.with_height(line_height + 16.0)
.with_height(theme.height)
.boxed()
},
)