WIP: Add ButtonSide element
This commit is contained in:
parent
e4871afaf3
commit
4ef59899d1
3 changed files with 165 additions and 17 deletions
|
@ -30,11 +30,11 @@ serde_derive.workspace = true
|
||||||
smallvec.workspace = true
|
smallvec.workspace = true
|
||||||
smol.workspace = true
|
smol.workspace = true
|
||||||
globset.workspace = true
|
globset.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
client = { path = "../client", features = ["test-support"] }
|
client = { path = "../client", features = ["test-support"] }
|
||||||
editor = { path = "../editor", features = ["test-support"] }
|
editor = { path = "../editor", features = ["test-support"] }
|
||||||
gpui = { path = "../gpui", features = ["test-support"] }
|
gpui = { path = "../gpui", features = ["test-support"] }
|
||||||
serde_json.workspace = true
|
|
||||||
workspace = { path = "../workspace", features = ["test-support"] }
|
workspace = { path = "../workspace", features = ["test-support"] }
|
||||||
unindent.workspace = true
|
unindent.workspace = true
|
||||||
|
|
|
@ -10,6 +10,10 @@ use editor::{
|
||||||
};
|
};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use globset::{Glob, GlobMatcher};
|
use globset::{Glob, GlobMatcher};
|
||||||
|
use gpui::color::Color;
|
||||||
|
use gpui::geometry::rect::RectF;
|
||||||
|
use gpui::json::{self, ToJson};
|
||||||
|
use gpui::SceneBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions,
|
actions,
|
||||||
elements::*,
|
elements::*,
|
||||||
|
@ -17,6 +21,7 @@ use gpui::{
|
||||||
Action, AnyElement, AnyViewHandle, AppContext, Entity, ModelContext, ModelHandle, Subscription,
|
Action, AnyElement, AnyViewHandle, AppContext, Entity, ModelContext, ModelHandle, Subscription,
|
||||||
Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
|
use gpui::{scene::Path, Border, LayoutContext};
|
||||||
use menu::Confirm;
|
use menu::Confirm;
|
||||||
use postage::stream::Stream;
|
use postage::stream::Stream;
|
||||||
use project::{search::SearchQuery, Entry, Project};
|
use project::{search::SearchQuery, Entry, Project};
|
||||||
|
@ -958,6 +963,113 @@ impl Default for ProjectSearchBar {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
type CreatePath = fn(RectF, Color) -> Path;
|
||||||
|
|
||||||
|
pub struct ButtonSide {
|
||||||
|
color: Color,
|
||||||
|
factory: CreatePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ButtonSide {
|
||||||
|
fn new(color: Color, factory: CreatePath) -> Self {
|
||||||
|
Self { color, factory }
|
||||||
|
}
|
||||||
|
pub fn left(color: Color) -> Self {
|
||||||
|
Self::new(color, left_button_side)
|
||||||
|
}
|
||||||
|
pub fn right(color: Color) -> Self {
|
||||||
|
Self::new(color, right_button_side)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left_button_side(bounds: RectF, color: Color) -> Path {
|
||||||
|
use gpui::geometry::PathBuilder;
|
||||||
|
let mut path = PathBuilder::new();
|
||||||
|
path.reset(bounds.lower_right());
|
||||||
|
path.line_to(bounds.upper_right());
|
||||||
|
let mut middle_point = bounds.origin();
|
||||||
|
let distance_to_line = (middle_point.y() - bounds.lower_left().y()) / 4.;
|
||||||
|
middle_point.set_y(middle_point.y() - distance_to_line);
|
||||||
|
path.curve_to(middle_point, bounds.origin());
|
||||||
|
let mut target = bounds.lower_left();
|
||||||
|
target.set_y(target.y() + distance_to_line);
|
||||||
|
path.line_to(target);
|
||||||
|
//path.curve_to(bounds.lower_right(), bounds.upper_right());
|
||||||
|
path.curve_to(bounds.lower_right(), bounds.lower_left());
|
||||||
|
path.build(color, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn right_button_side(bounds: RectF, color: Color) -> Path {
|
||||||
|
use gpui::geometry::PathBuilder;
|
||||||
|
let mut path = PathBuilder::new();
|
||||||
|
path.reset(bounds.lower_left());
|
||||||
|
path.line_to(bounds.origin());
|
||||||
|
let mut middle_point = bounds.upper_right();
|
||||||
|
let distance_to_line = (middle_point.y() - bounds.lower_right().y()) / 4.;
|
||||||
|
middle_point.set_y(middle_point.y() - distance_to_line);
|
||||||
|
path.curve_to(middle_point, bounds.upper_right());
|
||||||
|
let mut target = bounds.lower_right();
|
||||||
|
target.set_y(target.y() + distance_to_line);
|
||||||
|
path.line_to(target);
|
||||||
|
//path.curve_to(bounds.lower_right(), bounds.upper_right());
|
||||||
|
path.curve_to(bounds.lower_left(), bounds.lower_right());
|
||||||
|
path.build(color, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Element<ProjectSearchBar> for ButtonSide {
|
||||||
|
type LayoutState = ();
|
||||||
|
|
||||||
|
type PaintState = ();
|
||||||
|
|
||||||
|
fn layout(
|
||||||
|
&mut self,
|
||||||
|
constraint: gpui::SizeConstraint,
|
||||||
|
_: &mut ProjectSearchBar,
|
||||||
|
_: &mut LayoutContext<ProjectSearchBar>,
|
||||||
|
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
||||||
|
(constraint.max, ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
scene: &mut SceneBuilder,
|
||||||
|
bounds: RectF,
|
||||||
|
_: RectF,
|
||||||
|
_: &mut Self::LayoutState,
|
||||||
|
_: &mut ProjectSearchBar,
|
||||||
|
_: &mut ViewContext<ProjectSearchBar>,
|
||||||
|
) -> Self::PaintState {
|
||||||
|
scene.push_path((self.factory)(bounds, self.color));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rect_for_text_range(
|
||||||
|
&self,
|
||||||
|
_: Range<usize>,
|
||||||
|
_: RectF,
|
||||||
|
_: RectF,
|
||||||
|
_: &Self::LayoutState,
|
||||||
|
_: &Self::PaintState,
|
||||||
|
_: &ProjectSearchBar,
|
||||||
|
_: &ViewContext<ProjectSearchBar>,
|
||||||
|
) -> Option<RectF> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug(
|
||||||
|
&self,
|
||||||
|
bounds: RectF,
|
||||||
|
_: &Self::LayoutState,
|
||||||
|
_: &Self::PaintState,
|
||||||
|
_: &ProjectSearchBar,
|
||||||
|
_: &ViewContext<ProjectSearchBar>,
|
||||||
|
) -> gpui::json::Value {
|
||||||
|
json::json!({
|
||||||
|
"type": "ButtonSide",
|
||||||
|
"bounds": bounds.to_json(),
|
||||||
|
"color": self.color.to_json(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ProjectSearchBar {
|
impl ProjectSearchBar {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
@ -1276,14 +1388,32 @@ impl ProjectSearchBar {
|
||||||
let option = SearchOptions::REGEX;
|
let option = SearchOptions::REGEX;
|
||||||
MouseEventHandler::<Self, _>::new(option.bits as usize, cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(option.bits as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme
|
let mut style = theme
|
||||||
.search
|
.search
|
||||||
.option_button
|
.option_button
|
||||||
.in_state(is_active)
|
.in_state(is_active)
|
||||||
.style_for(state);
|
.style_for(state)
|
||||||
Label::new(icon, style.text.clone())
|
.clone();
|
||||||
.contained()
|
style.container.border.right = false;
|
||||||
.with_style(style.container)
|
Flex::row()
|
||||||
|
.with_child(
|
||||||
|
Label::new(icon, style.text.clone())
|
||||||
|
.contained()
|
||||||
|
.with_style(style.container),
|
||||||
|
)
|
||||||
|
.with_child(
|
||||||
|
ButtonSide::right(
|
||||||
|
style
|
||||||
|
.container
|
||||||
|
.background_color
|
||||||
|
.unwrap_or_else(gpui::color::Color::transparent_black),
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.constrained()
|
||||||
|
.with_max_width(theme.titlebar.avatar_ribbon.width / 2.)
|
||||||
|
.aligned()
|
||||||
|
.bottom(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||||
this.toggle_search_option(option, cx);
|
this.toggle_search_option(option, cx);
|
||||||
|
@ -1347,14 +1477,32 @@ impl ProjectSearchBar {
|
||||||
enum NormalSearchTag {}
|
enum NormalSearchTag {}
|
||||||
MouseEventHandler::<NormalSearchTag, _>::new(region_id, cx, |state, cx| {
|
MouseEventHandler::<NormalSearchTag, _>::new(region_id, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme
|
let mut style = theme
|
||||||
.search
|
.search
|
||||||
.option_button
|
.option_button
|
||||||
.in_state(is_active)
|
.in_state(is_active)
|
||||||
.style_for(state);
|
.style_for(state)
|
||||||
Label::new("Text", style.text.clone())
|
.clone();
|
||||||
.contained()
|
style.container.border.left = false;
|
||||||
.with_style(style.container)
|
Flex::row()
|
||||||
|
.with_child(
|
||||||
|
ButtonSide::left(
|
||||||
|
style
|
||||||
|
.container
|
||||||
|
.background_color
|
||||||
|
.unwrap_or_else(gpui::color::Color::transparent_black),
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.constrained()
|
||||||
|
.with_max_width(theme.titlebar.avatar_ribbon.width / 2.)
|
||||||
|
.aligned()
|
||||||
|
.bottom(),
|
||||||
|
)
|
||||||
|
.with_child(
|
||||||
|
Label::new("Text", style.text.clone())
|
||||||
|
.contained()
|
||||||
|
.with_style(style.container),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||||
if let Some(search) = this.active_project_search.as_mut() {
|
if let Some(search) = this.active_project_search.as_mut() {
|
||||||
|
@ -1592,7 +1740,9 @@ impl View for ProjectSearchBar {
|
||||||
.with_child(normal_search)
|
.with_child(normal_search)
|
||||||
.with_children(semantic_index)
|
.with_children(semantic_index)
|
||||||
.with_child(regex_button)
|
.with_child(regex_button)
|
||||||
.flex(1., true)
|
.constrained()
|
||||||
|
.with_height(theme.workspace.toolbar.height)
|
||||||
|
.contained()
|
||||||
.aligned()
|
.aligned()
|
||||||
.right(),
|
.right(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -44,11 +44,9 @@ export default function search(): any {
|
||||||
base: {
|
base: {
|
||||||
...text(theme.highest, "mono", "on"),
|
...text(theme.highest, "mono", "on"),
|
||||||
background: background(theme.highest, "on"),
|
background: background(theme.highest, "on"),
|
||||||
corner_radius: 2,
|
|
||||||
border: border(theme.highest, "on"),
|
border: border(theme.highest, "on"),
|
||||||
margin: {
|
|
||||||
right: 2,
|
|
||||||
},
|
|
||||||
padding: {
|
padding: {
|
||||||
bottom: 6,
|
bottom: 6,
|
||||||
left: 6,
|
left: 6,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue