Compare commits

..

8 Commits

Author SHA1 Message Date
Richard Feldman
0e1fe66a19 Show Lua script with syntax highlighting in assistant2 2025-03-10 11:26:12 -04:00
Marshall Bowers
ed52e759d7 docs: Fix language links (#26368)
This PR fixes some language links in the docs.

The Shell Script page wasn't being linked from `SUMMARY.md`, so no page
was being generated.

There were also some differences in the language lists in the sidebar
and on the top-level languages page.

Release Notes:

- N/A
2025-03-10 15:22:51 +00:00
Richard Feldman
6da099a9d7 Unsandbox Lua scripts (#26365)
Per a conversation with @nathansobo, have the Lua scripts run
unsandboxed for now (while this feature is behind the staff feature
flag).

Release Notes:

- N/A
2025-03-10 11:04:37 -04:00
Smit Barmase
5f159bc95e go_to_line: Fix goto line + mouse click jumps to previous scroll position (#26362)
Closes #20658

Now, when the "Go to Line" palette is open:  
- Clicking on the editor will dismiss the palette without changing the
scroll position. (PR change)
- Pressing Enter will jump to the line number entered in the palette.
(Unchanged)
- Pressing Escape will jump back to the previous cursor location.
(Unchanged)

Release Notes:

- Fixed an issue where clicking the editor with the mouse while the "Go
to Line" palette is open would cause it to jump to the previous scroll
position.
2025-03-10 20:33:07 +05:30
Marshall Bowers
a4462577bf Sort Cargo.tomls (#26367)
This PR sorts some `Cargo.toml`s that had become unsorted.

Release Notes:

- N/A
2025-03-10 14:48:21 +00:00
João Marcos
c147b58558 Remove redundant checks in do_stage_or_unstage_and_next (#26364)
Release Notes:

- N/A
2025-03-10 14:23:17 +00:00
Devzeth
84fe1bfe9b Recognize ixx as part of the cpp suffix (#26333)
Adds "ixx" as path suffix to be recognized for c++. 

> ixx documentation
https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp?view=msvc-

I've also added it to the icon file. 

Release Notes:

- N/A
2025-03-10 09:10:29 -05:00
Danilo Leal
657d7a911d Add logo for wgsl (WebGPU Shading Language) (#26360)
Was dabbling on the shaders these past few days and felt like we could
have the WGSL logo. This is based on the logo found on the GPU Web
repository: https://github.com/gpuweb/gpuweb/tree/main/logo

Release Notes:

- N/A
2025-03-10 09:44:19 -03:00
23 changed files with 261 additions and 334 deletions

1
Cargo.lock generated
View File

@@ -490,6 +490,7 @@ dependencies = [
"prompt_store", "prompt_store",
"proto", "proto",
"rand 0.8.5", "rand 0.8.5",
"rich_text",
"rope", "rope",
"serde", "serde",
"serde_json", "serde_json",

View File

@@ -8,6 +8,7 @@ members = [
"crates/assistant", "crates/assistant",
"crates/assistant2", "crates/assistant2",
"crates/assistant_context_editor", "crates/assistant_context_editor",
"crates/assistant_scripting",
"crates/assistant_settings", "crates/assistant_settings",
"crates/assistant_slash_command", "crates/assistant_slash_command",
"crates/assistant_slash_commands", "crates/assistant_slash_commands",
@@ -118,7 +119,6 @@ members = [
"crates/rope", "crates/rope",
"crates/rpc", "crates/rpc",
"crates/schema_generator", "crates/schema_generator",
"crates/assistant_scripting",
"crates/search", "crates/search",
"crates/semantic_index", "crates/semantic_index",
"crates/semantic_version", "crates/semantic_version",

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 13L1.5 5H11.5L6.5 13Z" fill="black"/>
<path d="M14 9H9L11.5 5L14 9Z" fill="black" fill-opacity="0.75"/>
<path d="M9 9L14 9L11.5 13L9 9Z" fill="black" fill-opacity="0.65"/>
<path d="M14 5L15.25 7L12.75 7L14 5Z" fill="black" fill-opacity="0.5"/>
<path d="M14 9L12.75 7H15.25L14 9Z" fill="black" fill-opacity="0.55"/>
</svg>

After

Width:  |  Height:  |  Size: 432 B

View File

@@ -21,6 +21,7 @@ test-support = [
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
assistant_context_editor.workspace = true assistant_context_editor.workspace = true
assistant_scripting.workspace = true
assistant_settings.workspace = true assistant_settings.workspace = true
assistant_slash_command.workspace = true assistant_slash_command.workspace = true
assistant_tool.workspace = true assistant_tool.workspace = true
@@ -63,7 +64,7 @@ serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
settings.workspace = true settings.workspace = true
smol.workspace = true smol.workspace = true
assistant_scripting.workspace = true rich_text.workspace = true
streaming_diff.workspace = true streaming_diff.workspace = true
telemetry_events.workspace = true telemetry_events.workspace = true
terminal.workspace = true terminal.workspace = true
@@ -82,8 +83,8 @@ zed_actions.workspace = true
[dev-dependencies] [dev-dependencies]
editor = { workspace = true, features = ["test-support"] } editor = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, "features" = ["test-support"] } gpui = { workspace = true, "features" = ["test-support"] }
indoc.workspace = true
language = { workspace = true, "features" = ["test-support"] } language = { workspace = true, "features" = ["test-support"] }
language_model = { workspace = true, "features" = ["test-support"] } language_model = { workspace = true, "features" = ["test-support"] }
project = { workspace = true, features = ["test-support"] } project = { workspace = true, features = ["test-support"] }
rand.workspace = true rand.workspace = true
indoc.workspace = true

View File

@@ -1,8 +1,7 @@
use std::sync::Arc;
use assistant_scripting::{ScriptId, ScriptState}; use assistant_scripting::{ScriptId, ScriptState};
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
use editor::{Editor, MultiBuffer}; use editor::{Editor, MultiBuffer};
use futures::FutureExt;
use gpui::{ use gpui::{
list, AbsoluteLength, AnyElement, App, ClickEvent, DefiniteLength, EdgesRefinement, Empty, list, AbsoluteLength, AnyElement, App, ClickEvent, DefiniteLength, EdgesRefinement, Empty,
Entity, Focusable, Length, ListAlignment, ListOffset, ListState, StyleRefinement, Subscription, Entity, Focusable, Length, ListAlignment, ListOffset, ListState, StyleRefinement, Subscription,
@@ -12,6 +11,8 @@ use language::{Buffer, LanguageRegistry};
use language_model::{LanguageModelRegistry, LanguageModelToolUseId, Role}; use language_model::{LanguageModelRegistry, LanguageModelToolUseId, Role};
use markdown::{Markdown, MarkdownStyle}; use markdown::{Markdown, MarkdownStyle};
use settings::Settings as _; use settings::Settings as _;
use std::ops::Range;
use std::sync::Arc;
use theme::ThemeSettings; use theme::ThemeSettings;
use ui::{prelude::*, Disclosure, KeyBinding}; use ui::{prelude::*, Disclosure, KeyBinding};
use util::ResultExt as _; use util::ResultExt as _;
@@ -21,6 +22,8 @@ use crate::thread::{MessageId, RequestKind, Thread, ThreadError, ThreadEvent};
use crate::thread_store::ThreadStore; use crate::thread_store::ThreadStore;
use crate::tool_use::{ToolUse, ToolUseStatus}; use crate::tool_use::{ToolUse, ToolUseStatus};
use crate::ui::ContextPill; use crate::ui::ContextPill;
use gpui::{HighlightStyle, StyledText};
use rich_text::{self, Highlight};
pub struct ActiveThread { pub struct ActiveThread {
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
@@ -809,11 +812,63 @@ impl ActiveThread {
let stdout = script.stdout_snapshot(); let stdout = script.stdout_snapshot();
let error = script.error(); let error = script.error();
let lua_language =
async { self.language_registry.language_for_name("Lua").await.ok() }
.now_or_never()
.flatten();
let source_display = if let Some(lua_language) = &lua_language {
let mut highlights = Vec::new();
let mut buf = String::new();
rich_text::render_code(
&mut buf,
&mut highlights,
&script.source,
lua_language,
);
let theme = cx.theme();
let gpui_highlights: Vec<(Range<usize>, HighlightStyle)> = highlights
.iter()
.map(|(range, highlight)| {
let style = match highlight {
Highlight::Code => Default::default(),
Highlight::Id(id) => {
id.style(theme.syntax()).unwrap_or_default()
}
Highlight::InlineCode(_) => Default::default(),
Highlight::Highlight(highlight) => *highlight,
_ => HighlightStyle::default(),
};
(range.clone(), style)
})
.collect();
StyledText::new(buf)
.with_highlights(gpui_highlights)
.into_any_element()
} else {
Label::new(script.source.clone())
.size(LabelSize::Small)
.buffer_font(cx)
.into_any_element()
};
parent.child( parent.child(
v_flex() v_flex()
.p_2() .p_2()
.bg(colors.editor_background) .bg(colors.editor_background)
.gap_2() .gap_2()
.child(
div()
.border_1()
.border_color(colors.border)
.p_2()
.bg(colors.editor_foreground.opacity(0.025))
.rounded_md()
.child(source_display),
)
.child(if stdout.is_empty() && error.is_none() { .child(if stdout.is_empty() && error.is_none() {
Label::new("No output yet") Label::new("No output yet")
.size(LabelSize::Small) .size(LabelSize::Small)

View File

@@ -3,6 +3,16 @@
-- Create a sandbox environment -- Create a sandbox environment
local sandbox = {} local sandbox = {}
-- For now, add all globals to `sandbox` (so there effectively is no sandbox).
-- We still need the logic below so that we can do things like overriding print() to write
-- to our in-memory log rather than to stdout, we will delete this loop (and re-enable
-- the I/O module being sandboxed below) to have things be sandboxed again.
for k, v in pairs(_G) do
if sandbox[k] == nil then
sandbox[k] = v
end
end
-- Allow access to standard libraries (safe subset) -- Allow access to standard libraries (safe subset)
sandbox.string = string sandbox.string = string
sandbox.table = table sandbox.table = table
@@ -25,8 +35,7 @@ local io = {}
io.open = sb_io_open io.open = sb_io_open
-- Add the sandboxed io library to the sandbox environment -- Add the sandboxed io library to the sandbox environment
sandbox.io = io -- sandbox.io = io -- Uncomment this line to re-enable sandboxed file I/O.
-- Load the script with the sandbox environment -- Load the script with the sandbox environment
local user_script_fn, err = load(user_script, nil, "t", sandbox) local user_script_fn, err = load(user_script, nil, "t", sandbox)

View File

@@ -119,6 +119,14 @@ impl ScriptSession {
let lua = Lua::new(); let lua = Lua::new();
lua.set_memory_limit(2 * 1024 * 1024 * 1024)?; // 2 GB lua.set_memory_limit(2 * 1024 * 1024 * 1024)?; // 2 GB
let globals = lua.globals(); let globals = lua.globals();
// Use the project root dir as the script's current working dir.
if let Some(root_dir) = &root_dir {
if let Some(root_dir) = root_dir.to_str() {
globals.set("cwd", root_dir)?;
}
}
globals.set( globals.set(
"sb_print", "sb_print",
lua.create_function({ lua.create_function({

View File

@@ -11639,7 +11639,7 @@ impl Editor {
fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) { fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
let snapshot = self.snapshot(window, cx); let snapshot = self.snapshot(window, cx);
let selection = self.selections.newest::<Point>(cx); let selection = self.selections.newest::<Point>(cx);
self.go_to_hunk_after_or_before_position( self.go_to_hunk_before_or_after_position(
&snapshot, &snapshot,
selection.head(), selection.head(),
Direction::Next, Direction::Next,
@@ -11648,7 +11648,7 @@ impl Editor {
); );
} }
fn go_to_hunk_after_or_before_position( fn go_to_hunk_before_or_after_position(
&mut self, &mut self,
snapshot: &EditorSnapshot, snapshot: &EditorSnapshot,
position: Point, position: Point,
@@ -11699,7 +11699,7 @@ impl Editor {
) { ) {
let snapshot = self.snapshot(window, cx); let snapshot = self.snapshot(window, cx);
let selection = self.selections.newest::<Point>(cx); let selection = self.selections.newest::<Point>(cx);
self.go_to_hunk_after_or_before_position( self.go_to_hunk_before_or_after_position(
&snapshot, &snapshot,
selection.head(), selection.head(),
Direction::Prev, Direction::Prev,
@@ -13861,21 +13861,6 @@ impl Editor {
return; return;
} }
let snapshot = self.snapshot(window, cx);
let newest_range = self.selections.newest::<Point>(cx).range();
let run_twice = snapshot
.hunks_for_ranges([newest_range])
.first()
.is_some_and(|hunk| {
let next_line = Point::new(hunk.row_range.end.0 + 1, 0);
self.hunk_after_position(&snapshot, next_line)
.is_some_and(|other| other.row_range == hunk.row_range)
});
if run_twice {
self.go_to_next_hunk(&GoToHunk, window, cx);
}
self.stage_or_unstage_diff_hunks(stage, ranges, cx); self.stage_or_unstage_diff_hunks(stage, ranges, cx);
self.go_to_next_hunk(&GoToHunk, window, cx); self.go_to_next_hunk(&GoToHunk, window, cx);
} }

View File

@@ -9014,7 +9014,7 @@ fn diff_hunk_controls(
let snapshot = editor.snapshot(window, cx); let snapshot = editor.snapshot(window, cx);
let position = let position =
hunk_range.end.to_point(&snapshot.buffer_snapshot); hunk_range.end.to_point(&snapshot.buffer_snapshot);
editor.go_to_hunk_after_or_before_position( editor.go_to_hunk_before_or_after_position(
&snapshot, &snapshot,
position, position,
Direction::Next, Direction::Next,
@@ -9050,7 +9050,7 @@ fn diff_hunk_controls(
let snapshot = editor.snapshot(window, cx); let snapshot = editor.snapshot(window, cx);
let point = let point =
hunk_range.start.to_point(&snapshot.buffer_snapshot); hunk_range.start.to_point(&snapshot.buffer_snapshot);
editor.go_to_hunk_after_or_before_position( editor.go_to_hunk_before_or_after_position(
&snapshot, &snapshot,
point, point,
Direction::Prev, Direction::Prev,

View File

@@ -41,8 +41,7 @@ use language_model::{
use menu::{Confirm, SecondaryConfirm, SelectFirst, SelectLast, SelectNext, SelectPrevious}; use menu::{Confirm, SecondaryConfirm, SelectFirst, SelectLast, SelectNext, SelectPrevious};
use multi_buffer::ExcerptInfo; use multi_buffer::ExcerptInfo;
use panel::{ use panel::{
panel_button, panel_editor_container, panel_editor_style, panel_filled_button, panel_editor_container, panel_editor_style, panel_filled_button, panel_icon_button, PanelHeader,
panel_icon_button, PanelHeader,
}; };
use project::{ use project::{
git::{GitEvent, Repository}, git::{GitEvent, Repository},
@@ -199,21 +198,6 @@ pub struct GitStatusEntry {
pub(crate) staging: StageStatus, pub(crate) staging: StageStatus,
} }
impl GitStatusEntry {
fn display_name(&self) -> String {
self.worktree_path
.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| self.worktree_path.to_string_lossy().into_owned())
}
fn parent_dir(&self) -> Option<String> {
self.worktree_path
.parent()
.map(|parent| parent.to_string_lossy().into_owned())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum TargetStatus { enum TargetStatus {
Staged, Staged,
@@ -255,9 +239,7 @@ pub struct GitPanel {
pending_serialization: Task<Option<()>>, pending_serialization: Task<Option<()>>,
pub(crate) project: Entity<Project>, pub(crate) project: Entity<Project>,
scroll_handle: UniformListScrollHandle, scroll_handle: UniformListScrollHandle,
vertical_scrollbar_state: ScrollbarState, scrollbar_state: ScrollbarState,
horizontal_scrollbar_state: ScrollbarState,
max_width_item_index: Option<usize>,
selected_entry: Option<usize>, selected_entry: Option<usize>,
marked_entries: Vec<usize>, marked_entries: Vec<usize>,
show_scrollbar: bool, show_scrollbar: bool,
@@ -364,9 +346,7 @@ impl GitPanel {
) )
.detach(); .detach();
let vertical_scrollbar_state = let scrollbar_state =
ScrollbarState::new(scroll_handle.clone()).parent_entity(&cx.entity());
let horizontal_scrollbar_state =
ScrollbarState::new(scroll_handle.clone()).parent_entity(&cx.entity()); ScrollbarState::new(scroll_handle.clone()).parent_entity(&cx.entity());
let mut git_panel = Self { let mut git_panel = Self {
@@ -392,9 +372,7 @@ impl GitPanel {
single_tracked_entry: None, single_tracked_entry: None,
project, project,
scroll_handle, scroll_handle,
vertical_scrollbar_state, scrollbar_state,
horizontal_scrollbar_state,
max_width_item_index: None,
selected_entry: None, selected_entry: None,
marked_entries: Vec::new(), marked_entries: Vec::new(),
show_scrollbar: false, show_scrollbar: false,
@@ -2016,7 +1994,6 @@ impl GitPanel {
let mut conflict_entries = Vec::new(); let mut conflict_entries = Vec::new();
let mut last_staged = None; let mut last_staged = None;
let mut staged_count = 0; let mut staged_count = 0;
let mut max_width_item: Option<(RepoPath, usize)> = None;
let Some(repo) = self.active_repository.as_ref() else { let Some(repo) = self.active_repository.as_ref() else {
// Just clear entries if no repository is active. // Just clear entries if no repository is active.
@@ -2062,21 +2039,6 @@ impl GitPanel {
last_staged = Some(entry.clone()); last_staged = Some(entry.clone());
} }
let width_estimate = Self::item_width_estimate(
entry.parent_dir().map(|s| s.len()).unwrap_or(0),
entry.display_name().len(),
);
match max_width_item.as_mut() {
Some((repo_path, estimate)) => {
if width_estimate > *estimate {
*repo_path = entry.repo_path.clone();
*estimate = width_estimate;
}
}
None => max_width_item = Some((entry.repo_path.clone(), width_estimate)),
}
if is_conflict { if is_conflict {
conflict_entries.push(entry); conflict_entries.push(entry);
} else if is_new { } else if is_new {
@@ -2149,15 +2111,6 @@ impl GitPanel {
.extend(new_entries.into_iter().map(GitListEntry::GitStatusEntry)); .extend(new_entries.into_iter().map(GitListEntry::GitStatusEntry));
} }
if let Some((repo_path, _)) = max_width_item {
self.max_width_item_index = self.entries.iter().position(|entry| match entry {
GitListEntry::GitStatusEntry(git_status_entry) => {
git_status_entry.repo_path == repo_path
}
GitListEntry::Header(_) => false,
});
}
self.update_counts(repo); self.update_counts(repo);
self.select_first_entry_if_none(cx); self.select_first_entry_if_none(cx);
@@ -2319,12 +2272,6 @@ impl GitPanel {
self.has_staged_changes() self.has_staged_changes()
} }
// eventually we'll need to take depth into account here
// if we add a tree view
fn item_width_estimate(path: usize, file_name: usize) -> usize {
path + file_name
}
pub(crate) fn render_generate_commit_message_button( pub(crate) fn render_generate_commit_message_button(
&self, &self,
cx: &Context<Self>, cx: &Context<Self>,
@@ -2475,10 +2422,8 @@ impl GitPanel {
} }
self.panel_header_container(window, cx) self.panel_header_container(window, cx)
.px_2()
.child( .child(
panel_button("Open Diff") Button::new("diff", "Open diff")
.color(Color::Muted)
.tooltip(Tooltip::for_action_title("Open diff", &Diff)) .tooltip(Tooltip::for_action_title("Open diff", &Diff))
.on_click(|_, _, cx| { .on_click(|_, _, cx| {
cx.defer(|cx| { cx.defer(|cx| {
@@ -2488,7 +2433,7 @@ impl GitPanel {
) )
.child(div().flex_grow()) // spacer .child(div().flex_grow()) // spacer
.child( .child(
panel_filled_button(text) Button::new("stage-unstage-all", text)
.tooltip(Tooltip::for_action_title(tooltip, action.as_ref())) .tooltip(Tooltip::for_action_title(tooltip, action.as_ref()))
.on_click(move |_, _, cx| { .on_click(move |_, _, cx| {
let action = action.boxed_clone(); let action = action.boxed_clone();
@@ -2641,14 +2586,15 @@ impl GitPanel {
.items_center() .items_center()
.py_2() .py_2()
.px(px(8.)) .px(px(8.))
// .bg(cx.theme().colors().background)
// .border_t_1()
.border_color(cx.theme().colors().border) .border_color(cx.theme().colors().border)
.gap_1p5() .gap_1p5()
.child( .child(
div() div()
.flex_grow() .flex_grow()
.overflow_hidden() .overflow_hidden()
.items_center() .max_w(relative(0.6))
.max_w(relative(0.85))
.h_full() .h_full()
.child( .child(
Label::new(commit.subject.clone()) Label::new(commit.subject.clone())
@@ -2712,12 +2658,12 @@ impl GitPanel {
) )
} }
fn render_vertical_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> { fn render_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
let scroll_bar_style = self.show_scrollbar(cx); let scroll_bar_style = self.show_scrollbar(cx);
let show_container = matches!(scroll_bar_style, ShowScrollbar::Always); let show_container = matches!(scroll_bar_style, ShowScrollbar::Always);
if !self.should_show_scrollbar(cx) if !self.should_show_scrollbar(cx)
|| !(self.show_scrollbar || self.vertical_scrollbar_state.is_dragging()) || !(self.show_scrollbar || self.scrollbar_state.is_dragging())
{ {
return None; return None;
} }
@@ -2746,7 +2692,7 @@ impl GitPanel {
.on_mouse_up( .on_mouse_up(
MouseButton::Left, MouseButton::Left,
cx.listener(|this, _, window, cx| { cx.listener(|this, _, window, cx| {
if !this.vertical_scrollbar_state.is_dragging() if !this.scrollbar_state.is_dragging()
&& !this.focus_handle.contains_focused(window, cx) && !this.focus_handle.contains_focused(window, cx)
{ {
this.hide_scrollbar(window, cx); this.hide_scrollbar(window, cx);
@@ -2761,79 +2707,7 @@ impl GitPanel {
})) }))
.children(Scrollbar::vertical( .children(Scrollbar::vertical(
// percentage as f32..end_offset as f32, // percentage as f32..end_offset as f32,
self.vertical_scrollbar_state.clone(), self.scrollbar_state.clone(),
)),
)
}
fn render_horizontal_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
let scroll_bar_style = self.show_scrollbar(cx);
let show_container = matches!(scroll_bar_style, ShowScrollbar::Always);
// if !self.should_show_scrollbar(cx)
// || !(self.show_scrollbar || self.horizontal_scrollbar_state.is_dragging())
// {
// return None;
// }
let scroll_handle = self.scroll_handle.0.borrow();
dbg!(scroll_handle.last_item_size);
// let longest_item_width = dbg!(scroll_handle.last_item_size)
// .filter(|size| dbg!(px(10.) * size.contents.width > size.item.width))?
// .contents
// .width
// .0 as f64;
// println!("Longest item width: {}", longest_item_width);
// if longest_item_width < scroll_handle.base_handle.bounds().size.width.0 as f64 {
// return None;
// }
Some(
div()
.id("git-panel-horizontal-scroll")
.occlude()
.flex_none()
.w_full()
.cursor_default()
.absolute()
.bottom_1()
.left_1()
.right_1()
.h(px(32.))
// .when(show_container, |this| this.pt_1().pb_1p5())
// .when(!show_container, |this| {
// this.bottom_1().left_1().right_1().h(px(32.))
// })
.on_mouse_move(cx.listener(|_, _, _, cx| {
cx.notify();
cx.stop_propagation()
}))
.on_hover(|_, _, cx| {
cx.stop_propagation();
})
.on_any_mouse_down(|_, _, cx| {
cx.stop_propagation();
})
.on_mouse_up(
MouseButton::Left,
cx.listener(|this, _, window, cx| {
if !this.horizontal_scrollbar_state.is_dragging()
&& !this.focus_handle.contains_focused(window, cx)
{
this.hide_scrollbar(window, cx);
cx.notify();
}
cx.stop_propagation();
}),
)
.on_scroll_wheel(cx.listener(|_, _, _, cx| {
cx.notify();
}))
.children(Scrollbar::horizontal(
// percentage as f32..end_offset as f32,
self.horizontal_scrollbar_state.clone(),
)), )),
) )
} }
@@ -2890,10 +2764,8 @@ impl GitPanel {
let entry_count = self.entries.len(); let entry_count = self.entries.len();
h_flex() h_flex()
// .debug_below()
.flex_1()
.size_full() .size_full()
.relative() .flex_grow()
.overflow_hidden() .overflow_hidden()
.child( .child(
uniform_list(cx.entity().clone(), "entries", entry_count, { uniform_list(cx.entity().clone(), "entries", entry_count, {
@@ -2928,10 +2800,8 @@ impl GitPanel {
} }
}) })
.size_full() .size_full()
.flex_grow()
.with_sizing_behavior(ListSizingBehavior::Auto) .with_sizing_behavior(ListSizingBehavior::Auto)
.with_horizontal_sizing_behavior(ListHorizontalSizingBehavior::Unconstrained) .with_horizontal_sizing_behavior(ListHorizontalSizingBehavior::Unconstrained)
.with_width_from_item(self.max_width_item_index)
.track_scroll(self.scroll_handle.clone()), .track_scroll(self.scroll_handle.clone()),
) )
.on_mouse_down( .on_mouse_down(
@@ -2940,8 +2810,7 @@ impl GitPanel {
this.deploy_panel_context_menu(event.position, window, cx) this.deploy_panel_context_menu(event.position, window, cx)
}), }),
) )
// .children(self.render_vertical_scrollbar(cx)) .children(self.render_scrollbar(cx))
.children(self.render_horizontal_scrollbar(cx))
} }
fn entry_label(&self, label: impl Into<SharedString>, color: Color) -> Label { fn entry_label(&self, label: impl Into<SharedString>, color: Color) -> Label {
@@ -3067,16 +2936,17 @@ impl GitPanel {
window: &Window, window: &Window,
cx: &Context<Self>, cx: &Context<Self>,
) -> AnyElement { ) -> AnyElement {
let display_name = entry.display_name(); let display_name = entry
.worktree_path
.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| entry.worktree_path.to_string_lossy().into_owned());
let worktree_path = entry.worktree_path.clone(); let worktree_path = entry.worktree_path.clone();
let selected = self.selected_entry == Some(ix); let selected = self.selected_entry == Some(ix);
let marked = self.marked_entries.contains(&ix); let marked = self.marked_entries.contains(&ix);
let status_style = GitPanelSettings::get_global(cx).status_style; let status_style = GitPanelSettings::get_global(cx).status_style;
let status = entry.status; let status = entry.status;
let modifiers = self.current_modifiers;
let shift_held = modifiers.shift;
let has_conflict = status.is_conflicted(); let has_conflict = status.is_conflicted();
let is_modified = status.is_modified(); let is_modified = status.is_modified();
let is_deleted = status.is_deleted(); let is_deleted = status.is_deleted();
@@ -3160,8 +3030,9 @@ impl GitPanel {
el.border_color(cx.theme().colors().border_focused) el.border_color(cx.theme().colors().border_focused)
}) })
.px(rems(0.75)) // ~12px .px(rems(0.75)) // ~12px
// .flex_none() .overflow_hidden()
.gap_1p5() .flex_none()
.gap(DynamicSpacing::Base04.rems(cx))
.bg(base_bg) .bg(base_bg)
.hover(|this| this.bg(hover_bg)) .hover(|this| this.bg(hover_bg))
.active(|this| this.bg(active_bg)) .active(|this| this.bg(active_bg))
@@ -3206,7 +3077,6 @@ impl GitPanel {
.flex_none() .flex_none()
.occlude() .occlude()
.cursor_pointer() .cursor_pointer()
.ml_neg_0p5()
.child( .child(
Checkbox::new(checkbox_id, is_staged) Checkbox::new(checkbox_id, is_staged)
.disabled(!has_write_access) .disabled(!has_write_access)
@@ -3228,44 +3098,26 @@ impl GitPanel {
}) })
}) })
.tooltip(move |window, cx| { .tooltip(move |window, cx| {
let is_staged = entry_staging.is_fully_staged(); let tooltip_name = if entry_staging.is_fully_staged() {
"Unstage"
let action = if is_staged { "Unstage" } else { "Stage" };
let tooltip_name = if shift_held {
format!("{} section", action)
} else { } else {
action.to_string() "Stage"
}; };
let meta = if shift_held { Tooltip::for_action(tooltip_name, &ToggleStaged, window, cx)
format!(
"Release shift to {} single entry",
action.to_lowercase()
)
} else {
format!("Shift click to {} section", action.to_lowercase())
};
Tooltip::with_meta(
tooltip_name,
Some(&ToggleStaged),
meta,
window,
cx,
)
}), }),
), ),
) )
.child(git_status_icon(status)) .child(git_status_icon(status, cx))
.child( .child(
h_flex() h_flex()
.items_center() .items_center()
.flex_1() .overflow_hidden()
// .overflow_hidden() .when_some(worktree_path.parent(), |this, parent| {
.when_some(entry.parent_dir(), |this, parent| { let parent_str = parent.to_string_lossy();
if !parent.is_empty() { if !parent_str.is_empty() {
this.child( this.child(
self.entry_label(format!("{}/", parent), path_color) self.entry_label(format!("{}/", parent_str), path_color)
.when(status.is_deleted(), |this| this.strikethrough()), .when(status.is_deleted(), |this| this.strikethrough()),
) )
} else { } else {
@@ -3664,11 +3516,7 @@ impl RenderOnce for PanelRepoFooter {
div().child( div().child(
Icon::new(IconName::GitBranchSmall) Icon::new(IconName::GitBranchSmall)
.size(IconSize::Small) .size(IconSize::Small)
.color(if single_repo { .color(Color::Muted),
Color::Disabled
} else {
Color::Muted
}),
), ),
) )
.child(repo_selector) .child(repo_selector)

View File

@@ -1,13 +1,13 @@
use ::settings::Settings; use ::settings::Settings;
use git::{ use git::{
repository::{Branch, Upstream, UpstreamTracking, UpstreamTrackingStatus}, repository::{Branch, Upstream, UpstreamTracking, UpstreamTrackingStatus},
status::{FileStatus, StatusCode, UnmergedStatus, UnmergedStatusCode}, status::FileStatus,
}; };
use git_panel_settings::GitPanelSettings; use git_panel_settings::GitPanelSettings;
use gpui::{App, Entity, FocusHandle}; use gpui::{App, Entity, FocusHandle};
use project::Project; use project::Project;
use project_diff::ProjectDiff; use project_diff::ProjectDiff;
use ui::prelude::*; use ui::{ActiveTheme, Color, Icon, IconName, IntoElement, SharedString};
use workspace::Workspace; use workspace::Workspace;
mod askpass_modal; mod askpass_modal;
@@ -84,8 +84,30 @@ pub fn init(cx: &mut App) {
.detach(); .detach();
} }
pub fn git_status_icon(status: FileStatus) -> impl IntoElement { // TODO: Add updated status colors to theme
GitStatusIcon::new(status) pub fn git_status_icon(status: FileStatus, cx: &App) -> impl IntoElement {
let (icon_name, color) = if status.is_conflicted() {
(
IconName::Warning,
cx.theme().colors().version_control_conflict,
)
} else if status.is_deleted() {
(
IconName::SquareMinus,
cx.theme().colors().version_control_deleted,
)
} else if status.is_modified() {
(
IconName::SquareDot,
cx.theme().colors().version_control_modified,
)
} else {
(
IconName::SquarePlus,
cx.theme().colors().version_control_added,
)
};
Icon::new(icon_name).color(Color::Custom(color))
} }
fn can_push_and_pull(project: &Entity<Project>, cx: &App) -> bool { fn can_push_and_pull(project: &Entity<Project>, cx: &App) -> bool {
@@ -427,79 +449,3 @@ mod remote_button {
} }
} }
} }
#[derive(IntoElement, IntoComponent)]
#[component(scope = "Version Control")]
pub struct GitStatusIcon {
status: FileStatus,
}
impl GitStatusIcon {
pub fn new(status: FileStatus) -> Self {
Self { status }
}
}
impl RenderOnce for GitStatusIcon {
fn render(self, _window: &mut ui::Window, cx: &mut App) -> impl IntoElement {
let status = self.status;
let (icon_name, color) = if status.is_conflicted() {
(
IconName::Warning,
cx.theme().colors().version_control_conflict,
)
} else if status.is_deleted() {
(
IconName::SquareMinus,
cx.theme().colors().version_control_deleted,
)
} else if status.is_modified() {
(
IconName::SquareDot,
cx.theme().colors().version_control_modified,
)
} else {
(
IconName::SquarePlus,
cx.theme().colors().version_control_added,
)
};
Icon::new(icon_name).color(Color::Custom(color))
}
}
// View this component preview using `workspace: open component-preview`
impl ComponentPreview for GitStatusIcon {
fn preview(_window: &mut Window, _cx: &mut App) -> AnyElement {
fn tracked_file_status(code: StatusCode) -> FileStatus {
FileStatus::Tracked(git::status::TrackedStatus {
index_status: code,
worktree_status: code,
})
}
let modified = tracked_file_status(StatusCode::Modified);
let added = tracked_file_status(StatusCode::Added);
let deleted = tracked_file_status(StatusCode::Deleted);
let conflict = UnmergedStatus {
first_head: UnmergedStatusCode::Updated,
second_head: UnmergedStatusCode::Updated,
}
.into();
v_flex()
.gap_6()
.children(vec![example_group(vec![
single_example("Modified", GitStatusIcon::new(modified).into_any_element()),
single_example("Added", GitStatusIcon::new(added).into_any_element()),
single_example("Deleted", GitStatusIcon::new(deleted).into_any_element()),
single_example(
"Conflicted",
GitStatusIcon::new(conflict).into_any_element(),
),
])])
.into_any_element()
}
}

View File

@@ -152,7 +152,10 @@ impl GoToLine {
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
match event { match event {
editor::EditorEvent::Blurred => cx.emit(DismissEvent), editor::EditorEvent::Blurred => {
self.prev_scroll_position.take();
cx.emit(DismissEvent)
}
editor::EditorEvent::BufferEdited { .. } => self.highlight_current_line(cx), editor::EditorEvent::BufferEdited { .. } => self.highlight_current_line(cx),
_ => {} _ => {}
} }

View File

@@ -1,6 +1,6 @@
name = "C++" name = "C++"
grammar = "cpp" grammar = "cpp"
path_suffixes = ["cc", "hh", "cpp", "h", "hpp", "cxx", "hxx", "c++", "ipp", "inl", "cu", "cuh", "C", "H"] path_suffixes = ["cc", "hh", "cpp", "h", "hpp", "cxx", "hxx", "c++", "ipp", "inl", "ixx", "cu", "cuh", "C", "H"]
line_comments = ["// ", "/// ", "//! "] line_comments = ["// ", "/// ", "//! "]
autoclose_before = ";:.,=}])>" autoclose_before = ";:.,=}])>"
brackets = [ brackets = [

View File

@@ -18,6 +18,8 @@ pub trait PanelHeader: workspace::Panel {
.w_full() .w_full()
.px_1() .px_1()
.flex_none() .flex_none()
.border_b_1()
.border_color(cx.theme().colors().border)
} }
} }

View File

@@ -136,10 +136,14 @@ impl ThemeColors {
terminal_ansi_dim_white: neutral().light().step_11(), terminal_ansi_dim_white: neutral().light().step_11(),
link_text_hover: orange().light().step_10(), link_text_hover: orange().light().step_10(),
version_control_added: ADDED_COLOR, version_control_added: ADDED_COLOR,
version_control_added_background: ADDED_COLOR.opacity(0.1),
version_control_deleted: REMOVED_COLOR, version_control_deleted: REMOVED_COLOR,
version_control_deleted_background: REMOVED_COLOR.opacity(0.1),
version_control_modified: MODIFIED_COLOR, version_control_modified: MODIFIED_COLOR,
version_control_modified_background: MODIFIED_COLOR.opacity(0.1),
version_control_renamed: MODIFIED_COLOR, version_control_renamed: MODIFIED_COLOR,
version_control_conflict: orange().light().step_12(), version_control_conflict: orange().light().step_12(),
version_control_conflict_background: orange().light().step_12().opacity(0.1),
version_control_ignored: gray().light().step_12(), version_control_ignored: gray().light().step_12(),
} }
} }
@@ -249,10 +253,14 @@ impl ThemeColors {
terminal_ansi_dim_white: neutral().dark().step_10(), terminal_ansi_dim_white: neutral().dark().step_10(),
link_text_hover: orange().dark().step_10(), link_text_hover: orange().dark().step_10(),
version_control_added: ADDED_COLOR, version_control_added: ADDED_COLOR,
version_control_added_background: ADDED_COLOR.opacity(0.1),
version_control_deleted: REMOVED_COLOR, version_control_deleted: REMOVED_COLOR,
version_control_deleted_background: REMOVED_COLOR.opacity(0.1),
version_control_modified: MODIFIED_COLOR, version_control_modified: MODIFIED_COLOR,
version_control_modified_background: MODIFIED_COLOR.opacity(0.1),
version_control_renamed: MODIFIED_COLOR, version_control_renamed: MODIFIED_COLOR,
version_control_conflict: orange().dark().step_12(), version_control_conflict: orange().dark().step_12(),
version_control_conflict_background: orange().dark().step_12().opacity(0.1),
version_control_ignored: gray().dark().step_12(), version_control_ignored: gray().dark().step_12(),
} }
} }

View File

@@ -190,10 +190,14 @@ pub(crate) fn zed_default_dark() -> Theme {
editor_foreground: hsla(218. / 360., 14. / 100., 71. / 100., 1.), editor_foreground: hsla(218. / 360., 14. / 100., 71. / 100., 1.),
link_text_hover: blue, link_text_hover: blue,
version_control_added: ADDED_COLOR, version_control_added: ADDED_COLOR,
version_control_added_background: ADDED_COLOR.opacity(0.1),
version_control_deleted: REMOVED_COLOR, version_control_deleted: REMOVED_COLOR,
version_control_deleted_background: REMOVED_COLOR.opacity(0.1),
version_control_modified: MODIFIED_COLOR, version_control_modified: MODIFIED_COLOR,
version_control_modified_background: MODIFIED_COLOR.opacity(0.1),
version_control_renamed: MODIFIED_COLOR, version_control_renamed: MODIFIED_COLOR,
version_control_conflict: crate::orange().light().step_12(), version_control_conflict: crate::orange().light().step_12(),
version_control_conflict_background: crate::orange().light().step_12().opacity(0.1),
version_control_ignored: crate::gray().light().step_12(), version_control_ignored: crate::gray().light().step_12(),
}, },
status: StatusColors { status: StatusColors {

View File

@@ -85,7 +85,7 @@ const FILE_SUFFIXES_BY_ICON_KEY: &[(&str, &[&str])] = &[
("coffeescript", &["coffee"]), ("coffeescript", &["coffee"]),
( (
"cpp", "cpp",
&["c++", "cc", "cpp", "cxx", "hh", "hpp", "hxx", "inl"], &["c++", "cc", "cpp", "cxx", "hh", "hpp", "hxx", "inl", "ixx"],
), ),
("crystal", &["cr", "ecr"]), ("crystal", &["cr", "ecr"]),
("csharp", &["cs"]), ("csharp", &["cs"]),
@@ -264,6 +264,7 @@ const FILE_SUFFIXES_BY_ICON_KEY: &[(&str, &[&str])] = &[
("vs_sln", &["sln"]), ("vs_sln", &["sln"]),
("vs_suo", &["suo"]), ("vs_suo", &["suo"]),
("vue", &["vue"]), ("vue", &["vue"]),
("wgsl", &["wgsl"]),
("zig", &["zig"]), ("zig", &["zig"]),
]; ];
@@ -348,6 +349,7 @@ const FILE_ICONS: &[(&str, &str)] = &[
("vs_sln", "icons/file_icons/file.svg"), ("vs_sln", "icons/file_icons/file.svg"),
("vs_suo", "icons/file_icons/file.svg"), ("vs_suo", "icons/file_icons/file.svg"),
("vue", "icons/file_icons/vue.svg"), ("vue", "icons/file_icons/vue.svg"),
("wgsl", "icons/file_icons/wgsl.svg"),
("zig", "icons/file_icons/zig.svg"), ("zig", "icons/file_icons/zig.svg"),
]; ];

View File

@@ -557,14 +557,26 @@ pub struct ThemeColorsContent {
#[serde(rename = "version_control.added")] #[serde(rename = "version_control.added")]
pub version_control_added: Option<String>, pub version_control_added: Option<String>,
/// Added version control background color.
#[serde(rename = "version_control.added_background")]
pub version_control_added_background: Option<String>,
/// Deleted version control color. /// Deleted version control color.
#[serde(rename = "version_control.deleted")] #[serde(rename = "version_control.deleted")]
pub version_control_deleted: Option<String>, pub version_control_deleted: Option<String>,
/// Deleted version control background color.
#[serde(rename = "version_control.deleted_background")]
pub version_control_deleted_background: Option<String>,
/// Modified version control color. /// Modified version control color.
#[serde(rename = "version_control.modified")] #[serde(rename = "version_control.modified")]
pub version_control_modified: Option<String>, pub version_control_modified: Option<String>,
/// Modified version control background color.
#[serde(rename = "version_control.modified_background")]
pub version_control_modified_background: Option<String>,
/// Renamed version control color. /// Renamed version control color.
#[serde(rename = "version_control.renamed")] #[serde(rename = "version_control.renamed")]
pub version_control_renamed: Option<String>, pub version_control_renamed: Option<String>,
@@ -573,6 +585,10 @@ pub struct ThemeColorsContent {
#[serde(rename = "version_control.conflict")] #[serde(rename = "version_control.conflict")]
pub version_control_conflict: Option<String>, pub version_control_conflict: Option<String>,
/// Conflict version control background color.
#[serde(rename = "version_control.conflict_background")]
pub version_control_conflict_background: Option<String>,
/// Ignored version control color. /// Ignored version control color.
#[serde(rename = "version_control.ignored")] #[serde(rename = "version_control.ignored")]
pub version_control_ignored: Option<String>, pub version_control_ignored: Option<String>,
@@ -984,14 +1000,26 @@ impl ThemeColorsContent {
.version_control_added .version_control_added
.as_ref() .as_ref()
.and_then(|color| try_parse_color(color).ok()), .and_then(|color| try_parse_color(color).ok()),
version_control_added_background: self
.version_control_added_background
.as_ref()
.and_then(|color| try_parse_color(color).ok()),
version_control_deleted: self version_control_deleted: self
.version_control_deleted .version_control_deleted
.as_ref() .as_ref()
.and_then(|color| try_parse_color(color).ok()), .and_then(|color| try_parse_color(color).ok()),
version_control_deleted_background: self
.version_control_deleted_background
.as_ref()
.and_then(|color| try_parse_color(color).ok()),
version_control_modified: self version_control_modified: self
.version_control_modified .version_control_modified
.as_ref() .as_ref()
.and_then(|color| try_parse_color(color).ok()), .and_then(|color| try_parse_color(color).ok()),
version_control_modified_background: self
.version_control_modified_background
.as_ref()
.and_then(|color| try_parse_color(color).ok()),
version_control_renamed: self version_control_renamed: self
.version_control_renamed .version_control_renamed
.as_ref() .as_ref()
@@ -1000,6 +1028,10 @@ impl ThemeColorsContent {
.version_control_conflict .version_control_conflict
.as_ref() .as_ref()
.and_then(|color| try_parse_color(color).ok()), .and_then(|color| try_parse_color(color).ok()),
version_control_conflict_background: self
.version_control_conflict_background
.as_ref()
.and_then(|color| try_parse_color(color).ok()),
version_control_ignored: self version_control_ignored: self
.version_control_ignored .version_control_ignored
.as_ref() .as_ref()

View File

@@ -246,14 +246,22 @@ pub struct ThemeColors {
/// Represents an added entry or hunk in vcs, like git. /// Represents an added entry or hunk in vcs, like git.
pub version_control_added: Hsla, pub version_control_added: Hsla,
/// Represents the line background of an added entry or hunk in vcs, like git.
pub version_control_added_background: Hsla,
/// Represents a deleted entry in version control systems. /// Represents a deleted entry in version control systems.
pub version_control_deleted: Hsla, pub version_control_deleted: Hsla,
/// Represents the background color for deleted entries in version control systems.
pub version_control_deleted_background: Hsla,
/// Represents a modified entry in version control systems. /// Represents a modified entry in version control systems.
pub version_control_modified: Hsla, pub version_control_modified: Hsla,
/// Represents the background color for modified entries in version control systems.
pub version_control_modified_background: Hsla,
/// Represents a renamed entry in version control systems. /// Represents a renamed entry in version control systems.
pub version_control_renamed: Hsla, pub version_control_renamed: Hsla,
/// Represents a conflicting entry in version control systems. /// Represents a conflicting entry in version control systems.
pub version_control_conflict: Hsla, pub version_control_conflict: Hsla,
/// Represents the background color for conflicting entries in version control systems.
pub version_control_conflict_background: Hsla,
/// Represents an ignored entry in version control systems. /// Represents an ignored entry in version control systems.
pub version_control_ignored: Hsla, pub version_control_ignored: Hsla,
} }
@@ -358,10 +366,14 @@ pub enum ThemeColorField {
TerminalAnsiDimWhite, TerminalAnsiDimWhite,
LinkTextHover, LinkTextHover,
VersionControlAdded, VersionControlAdded,
VersionControlAddedBackground,
VersionControlDeleted, VersionControlDeleted,
VersionControlDeletedBackground,
VersionControlModified, VersionControlModified,
VersionControlModifiedBackground,
VersionControlRenamed, VersionControlRenamed,
VersionControlConflict, VersionControlConflict,
VersionControlConflictBackground,
VersionControlIgnored, VersionControlIgnored,
} }
@@ -473,10 +485,20 @@ impl ThemeColors {
ThemeColorField::TerminalAnsiDimWhite => self.terminal_ansi_dim_white, ThemeColorField::TerminalAnsiDimWhite => self.terminal_ansi_dim_white,
ThemeColorField::LinkTextHover => self.link_text_hover, ThemeColorField::LinkTextHover => self.link_text_hover,
ThemeColorField::VersionControlAdded => self.version_control_added, ThemeColorField::VersionControlAdded => self.version_control_added,
ThemeColorField::VersionControlAddedBackground => self.version_control_added_background,
ThemeColorField::VersionControlDeleted => self.version_control_deleted, ThemeColorField::VersionControlDeleted => self.version_control_deleted,
ThemeColorField::VersionControlDeletedBackground => {
self.version_control_deleted_background
}
ThemeColorField::VersionControlModified => self.version_control_modified, ThemeColorField::VersionControlModified => self.version_control_modified,
ThemeColorField::VersionControlModifiedBackground => {
self.version_control_modified_background
}
ThemeColorField::VersionControlRenamed => self.version_control_renamed, ThemeColorField::VersionControlRenamed => self.version_control_renamed,
ThemeColorField::VersionControlConflict => self.version_control_conflict, ThemeColorField::VersionControlConflict => self.version_control_conflict,
ThemeColorField::VersionControlConflictBackground => {
self.version_control_conflict_background
}
ThemeColorField::VersionControlIgnored => self.version_control_ignored, ThemeColorField::VersionControlIgnored => self.version_control_ignored,
} }
} }

View File

@@ -6,7 +6,9 @@ use crate::{
prelude::*, Color, DynamicSpacing, ElevationIndex, IconPosition, KeyBinding, prelude::*, Color, DynamicSpacing, ElevationIndex, IconPosition, KeyBinding,
KeybindingPosition, TintColor, KeybindingPosition, TintColor,
}; };
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, IconName, IconSize, Label}; use crate::{
ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, IconName, IconSize, Label, LineHeightStyle,
};
use super::button_icon::ButtonIcon; use super::button_icon::ButtonIcon;
@@ -446,6 +448,7 @@ impl RenderOnce for Button {
.color(label_color) .color(label_color)
.size(self.label_size.unwrap_or_default()) .size(self.label_size.unwrap_or_default())
.when_some(self.alpha, |this, alpha| this.alpha(alpha)) .when_some(self.alpha, |this, alpha| this.alpha(alpha))
.line_height_style(LineHeightStyle::UiLabel)
.when(self.truncate, |this| this.truncate()), .when(self.truncate, |this| this.truncate()),
) )
.children(self.key_binding), .children(self.key_binding),

View File

@@ -1,5 +1,6 @@
use gpui::{ use gpui::{
div, hsla, prelude::*, AnyElement, AnyView, ElementId, Hsla, IntoElement, Styled, Window, div, hsla, prelude::*, AnyElement, AnyView, CursorStyle, ElementId, Hsla, IntoElement, Styled,
Window,
}; };
use std::sync::Arc; use std::sync::Arc;
@@ -140,14 +141,14 @@ impl Checkbox {
match self.style.clone() { match self.style.clone() {
ToggleStyle::Ghost => cx.theme().colors().border, ToggleStyle::Ghost => cx.theme().colors().border,
ToggleStyle::ElevationBased(_) => cx.theme().colors().border, ToggleStyle::ElevationBased(elevation) => elevation.on_elevation_bg(cx),
ToggleStyle::Custom(color) => color.opacity(0.3), ToggleStyle::Custom(color) => color.opacity(0.3),
} }
} }
/// container size /// container size
pub fn container_size() -> Pixels { pub fn container_size(cx: &App) -> Rems {
px(20.0) DynamicSpacing::Base20.rems(cx)
} }
} }
@@ -156,21 +157,21 @@ impl RenderOnce for Checkbox {
let group_id = format!("checkbox_group_{:?}", self.id); let group_id = format!("checkbox_group_{:?}", self.id);
let color = if self.disabled { let color = if self.disabled {
Color::Disabled Color::Disabled
} else if self.placeholder {
Color::Placeholder
} else { } else {
Color::Selected Color::Selected
}; };
let icon = match self.toggle_state { let icon = match self.toggle_state {
ToggleState::Selected => { ToggleState::Selected => Some(if self.placeholder {
if self.placeholder { Icon::new(IconName::Circle)
None .size(IconSize::XSmall)
} else { .color(color)
Some( } else {
Icon::new(IconName::Check) Icon::new(IconName::Check)
.size(IconSize::Small) .size(IconSize::Small)
.color(color), .color(color)
) }),
}
}
ToggleState::Indeterminate => { ToggleState::Indeterminate => {
Some(Icon::new(IconName::Dash).size(IconSize::Small).color(color)) Some(Icon::new(IconName::Dash).size(IconSize::Small).color(color))
} }
@@ -179,9 +180,8 @@ impl RenderOnce for Checkbox {
let bg_color = self.bg_color(cx); let bg_color = self.bg_color(cx);
let border_color = self.border_color(cx); let border_color = self.border_color(cx);
let hover_border_color = border_color.alpha(0.7);
let size = Self::container_size(); let size = Self::container_size(cx);
let checkbox = h_flex() let checkbox = h_flex()
.id(self.id.clone()) .id(self.id.clone())
@@ -195,27 +195,22 @@ impl RenderOnce for Checkbox {
.flex_none() .flex_none()
.justify_center() .justify_center()
.items_center() .items_center()
.m_1() .m(DynamicSpacing::Base04.px(cx))
.size_4() .size(DynamicSpacing::Base16.rems(cx))
.rounded_xs() .rounded_xs()
.bg(bg_color) .bg(bg_color)
.border_1() .border_1()
.border_color(border_color) .border_color(border_color)
.when(self.disabled, |this| this.cursor_not_allowed()) .when(self.disabled, |this| {
this.cursor(CursorStyle::OperationNotAllowed)
})
.when(self.disabled, |this| { .when(self.disabled, |this| {
this.bg(cx.theme().colors().element_disabled.opacity(0.6)) this.bg(cx.theme().colors().element_disabled.opacity(0.6))
}) })
.when(!self.disabled, |this| { .when(!self.disabled, |this| {
this.group_hover(group_id.clone(), |el| el.border_color(hover_border_color)) this.group_hover(group_id.clone(), |el| {
}) el.bg(cx.theme().colors().element_hover)
.when(self.placeholder, |this| { })
this.child(
div()
.flex_none()
.rounded_full()
.bg(color.color(cx).alpha(0.5))
.size(px(4.)),
)
}) })
.children(icon), .children(icon),
); );
@@ -527,12 +522,6 @@ impl ComponentPreview for Checkbox {
Checkbox::new("checkbox_unselected", ToggleState::Unselected) Checkbox::new("checkbox_unselected", ToggleState::Unselected)
.into_any_element(), .into_any_element(),
), ),
single_example(
"Placeholder",
Checkbox::new("checkbox_indeterminate", ToggleState::Selected)
.placeholder(true)
.into_any_element(),
),
single_example( single_example(
"Indeterminate", "Indeterminate",
Checkbox::new("checkbox_indeterminate", ToggleState::Indeterminate) Checkbox::new("checkbox_indeterminate", ToggleState::Indeterminate)

View File

@@ -115,6 +115,7 @@
- [Rust](./languages/rust.md) - [Rust](./languages/rust.md)
- [Scala](./languages/scala.md) - [Scala](./languages/scala.md)
- [Scheme](./languages/scheme.md) - [Scheme](./languages/scheme.md)
- [Shell Script](./languages/sh.md)
- [Svelte](./languages/svelte.md) - [Svelte](./languages/svelte.md)
- [Swift](./languages/swift.md) - [Swift](./languages/swift.md)
- [Tailwind CSS](./languages/tailwindcss.md) - [Tailwind CSS](./languages/tailwindcss.md)

View File

@@ -28,6 +28,7 @@ Zed supports hundreds of programming languages and text formats. Some work out-o
- [Go](./languages/go.md) - [Go](./languages/go.md)
- [Groovy](./languages/groovy.md) - [Groovy](./languages/groovy.md)
- [Haskell](./languages/haskell.md) - [Haskell](./languages/haskell.md)
- [Helm](./languages/helm.md)
- [HTML](./languages/html.md) - [HTML](./languages/html.md)
- [Java](./languages/java.md) - [Java](./languages/java.md)
- [JavaScript](./languages/javascript.md) - [JavaScript](./languages/javascript.md)
@@ -58,7 +59,7 @@ Zed supports hundreds of programming languages and text formats. Some work out-o
- [Shell Script](./languages/sh.md) - [Shell Script](./languages/sh.md)
- [Svelte](./languages/svelte.md) - [Svelte](./languages/svelte.md)
- [Swift](./languages/swift.md) - [Swift](./languages/swift.md)
- [TailwindCSS](./languages/tailwindcss.md) - [Tailwind CSS](./languages/tailwindcss.md)
- [Terraform](./languages/terraform.md) - [Terraform](./languages/terraform.md)
- [TOML](./languages/toml.md) - [TOML](./languages/toml.md)
- [TypeScript](./languages/typescript.md) - [TypeScript](./languages/typescript.md)