Mainline GPUI2 UI work (#3079)
This PR mainlines the current state of new GPUI2-based UI from the `gpui2-ui` branch. Release Notes: - N/A --------- Co-authored-by: Nate Butler <iamnbutler@gmail.com> Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Co-authored-by: Nate <nate@zed.dev>
This commit is contained in:
parent
08361eb84e
commit
9e1f7c4c18
39 changed files with 1047 additions and 399 deletions
|
@ -12,6 +12,8 @@ path = "src/storybook.rs"
|
|||
anyhow.workspace = true
|
||||
clap = { version = "4.4", features = ["derive", "string"] }
|
||||
chrono = "0.4"
|
||||
fs = { path = "../fs" }
|
||||
futures.workspace = true
|
||||
gpui2 = { path = "../gpui2" }
|
||||
itertools = "0.11.0"
|
||||
log.workspace = true
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use ui::prelude::*;
|
||||
use ui::Breadcrumb;
|
||||
use ui::{Breadcrumb, HighlightedText, Symbol};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
|
@ -8,9 +11,35 @@ pub struct BreadcrumbStory {}
|
|||
|
||||
impl BreadcrumbStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Breadcrumb>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Breadcrumb::new())
|
||||
.child(Breadcrumb::new(
|
||||
PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(),
|
||||
vec![
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "impl ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "BreadcrumbStory".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "fn ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "render".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
],
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@ pub struct BufferStory {}
|
|||
|
||||
impl BufferStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Buffer<V>>(cx))
|
||||
.child(Story::title_for::<_, Buffer>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(div().w(rems(64.)).h_96().child(empty_buffer_example()))
|
||||
.child(Story::label(cx, "Hello World (Rust)"))
|
||||
|
@ -21,14 +23,14 @@ impl BufferStory {
|
|||
div()
|
||||
.w(rems(64.))
|
||||
.h_96()
|
||||
.child(hello_world_rust_buffer_example(cx)),
|
||||
.child(hello_world_rust_buffer_example(&theme)),
|
||||
)
|
||||
.child(Story::label(cx, "Hello World (Rust) with Status"))
|
||||
.child(
|
||||
div()
|
||||
.w(rems(64.))
|
||||
.h_96()
|
||||
.child(hello_world_rust_buffer_with_status_example(cx)),
|
||||
.child(hello_world_rust_buffer_with_status_example(&theme)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use chrono::DateTime;
|
||||
use ui::prelude::*;
|
||||
use ui::{ChatMessage, ChatPanel};
|
||||
use ui::{ChatMessage, ChatPanel, Panel};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
|
@ -12,23 +12,35 @@ impl ChatPanelStory {
|
|||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ChatPanel<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(ChatPanel::new(ScrollState::default()))
|
||||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| vec![ChatPanel::new(ScrollState::default()).into_any()],
|
||||
Box::new(()),
|
||||
))
|
||||
.child(Story::label(cx, "With Mesages"))
|
||||
.child(ChatPanel::new(ScrollState::default()).with_messages(vec![
|
||||
ChatMessage::new(
|
||||
"osiewicz".to_string(),
|
||||
"is this thing on?".to_string(),
|
||||
DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z")
|
||||
.unwrap()
|
||||
.naive_local(),
|
||||
),
|
||||
ChatMessage::new(
|
||||
"maxdeviant".to_string(),
|
||||
"Reading you loud and clear!".to_string(),
|
||||
DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z")
|
||||
.unwrap()
|
||||
.naive_local(),
|
||||
),
|
||||
]))
|
||||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| {
|
||||
vec![ChatPanel::new(ScrollState::default())
|
||||
.with_messages(vec![
|
||||
ChatMessage::new(
|
||||
"osiewicz".to_string(),
|
||||
"is this thing on?".to_string(),
|
||||
DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z")
|
||||
.unwrap()
|
||||
.naive_local(),
|
||||
),
|
||||
ChatMessage::new(
|
||||
"maxdeviant".to_string(),
|
||||
"Reading you loud and clear!".to_string(),
|
||||
DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z")
|
||||
.unwrap()
|
||||
.naive_local(),
|
||||
),
|
||||
])
|
||||
.into_any()]
|
||||
},
|
||||
Box::new(()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ impl FacepileStory {
|
|||
let players = static_players();
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ui::Facepile>(cx))
|
||||
.child(Story::title_for::<_, Facepile>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(
|
||||
div()
|
||||
|
|
|
@ -14,9 +14,10 @@ impl PanelStory {
|
|||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| {
|
||||
(0..100)
|
||||
.map(|ix| Label::new(format!("Item {}", ix + 1)).into_any())
|
||||
.collect()
|
||||
vec![div()
|
||||
.overflow_y_scroll(ScrollState::default())
|
||||
.children((0..100).map(|ix| Label::new(format!("Item {}", ix + 1))))
|
||||
.into_any()]
|
||||
},
|
||||
Box::new(()),
|
||||
))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ui::prelude::*;
|
||||
use ui::ProjectPanel;
|
||||
use ui::{Panel, ProjectPanel};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
|
@ -11,6 +11,10 @@ impl ProjectPanelStory {
|
|||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ProjectPanel<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(ProjectPanel::new(ScrollState::default()))
|
||||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| vec![ProjectPanel::new(ScrollState::default()).into_any()],
|
||||
Box::new(()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ui::prelude::*;
|
||||
use ui::TabBar;
|
||||
use ui::{Tab, TabBar};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
|
@ -11,6 +11,36 @@ impl TabBarStory {
|
|||
Story::container(cx)
|
||||
.child(Story::title_for::<_, TabBar<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(TabBar::new(ScrollState::default()))
|
||||
.child(TabBar::new(vec![
|
||||
Tab::new()
|
||||
.title("Cargo.toml".to_string())
|
||||
.current(false)
|
||||
.git_status(GitStatus::Modified),
|
||||
Tab::new()
|
||||
.title("Channels Panel".to_string())
|
||||
.current(false),
|
||||
Tab::new()
|
||||
.title("channels_panel.rs".to_string())
|
||||
.current(true)
|
||||
.git_status(GitStatus::Modified),
|
||||
Tab::new()
|
||||
.title("workspace.rs".to_string())
|
||||
.current(false)
|
||||
.git_status(GitStatus::Modified),
|
||||
Tab::new()
|
||||
.title("icon_button.rs".to_string())
|
||||
.current(false),
|
||||
Tab::new()
|
||||
.title("storybook.rs".to_string())
|
||||
.current(false)
|
||||
.git_status(GitStatus::Created),
|
||||
Tab::new().title("theme.rs".to_string()).current(false),
|
||||
Tab::new()
|
||||
.title("theme_registry.rs".to_string())
|
||||
.current(false),
|
||||
Tab::new()
|
||||
.title("styleable_helpers.rs".to_string())
|
||||
.current(false),
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ui::prelude::*;
|
||||
use ui::Toolbar;
|
||||
use ui::{theme, Breadcrumb, HighlightColor, HighlightedText, Icon, IconButton, Symbol, Toolbar};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
|
@ -8,9 +12,59 @@ pub struct ToolbarStory {}
|
|||
|
||||
impl ToolbarStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
struct LeftItemsPayload {
|
||||
pub theme: Arc<Theme>,
|
||||
}
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Toolbar>(cx))
|
||||
.child(Story::title_for::<_, Toolbar<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Toolbar::new())
|
||||
.child(Toolbar::new(
|
||||
|_, payload| {
|
||||
let payload = payload.downcast_ref::<LeftItemsPayload>().unwrap();
|
||||
|
||||
let theme = payload.theme.clone();
|
||||
|
||||
vec![Breadcrumb::new(
|
||||
PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(),
|
||||
vec![
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "impl ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "ToolbarStory".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "fn ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "render".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
],
|
||||
)
|
||||
.into_any()]
|
||||
},
|
||||
Box::new(LeftItemsPayload {
|
||||
theme: theme.clone(),
|
||||
}),
|
||||
|_, _| {
|
||||
vec![
|
||||
IconButton::new(Icon::InlayHint).into_any(),
|
||||
IconButton::new(Icon::MagnifyingGlass).into_any(),
|
||||
IconButton::new(Icon::MagicWand).into_any(),
|
||||
]
|
||||
},
|
||||
Box::new(()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct AvatarStory {}
|
|||
impl AvatarStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ui::Avatar>(cx))
|
||||
.child(Story::title_for::<_, Avatar>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Avatar::new(
|
||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||
|
|
|
@ -12,7 +12,7 @@ impl IconStory {
|
|||
let icons = Icon::iter();
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ui::IconElement>(cx))
|
||||
.child(Story::title_for::<_, IconElement>(cx))
|
||||
.child(Story::label(cx, "All Icons"))
|
||||
.child(div().flex().gap_3().children(icons.map(IconElement::new)))
|
||||
}
|
||||
|
|
|
@ -19,5 +19,8 @@ impl KitchenSinkStory {
|
|||
.child(div().flex().flex_col().children_any(element_stories))
|
||||
.child(Story::label(cx, "Components"))
|
||||
.child(div().flex().flex_col().children_any(component_stories))
|
||||
// Add a bit of space at the bottom of the kitchen sink so elements
|
||||
// don't end up squished right up against the bottom of the screen.
|
||||
.child(div().p_4())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ mod stories;
|
|||
mod story;
|
||||
mod story_selector;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{process::Command, sync::Arc};
|
||||
|
||||
use ::theme as legacy_theme;
|
||||
use clap::Parser;
|
||||
|
@ -38,11 +38,44 @@ struct Args {
|
|||
theme: Option<String>,
|
||||
}
|
||||
|
||||
async fn watch_zed_changes(fs: Arc<dyn fs::Fs>) -> Option<()> {
|
||||
if std::env::var("ZED_HOT_RELOAD").is_err() {
|
||||
return None;
|
||||
}
|
||||
use futures::StreamExt;
|
||||
let mut events = fs
|
||||
.watch(".".as_ref(), std::time::Duration::from_millis(100))
|
||||
.await;
|
||||
let mut current_child: Option<std::process::Child> = None;
|
||||
while let Some(events) = events.next().await {
|
||||
if !events.iter().any(|event| {
|
||||
event
|
||||
.path
|
||||
.to_str()
|
||||
.map(|path| path.contains("/crates/"))
|
||||
.unwrap_or_default()
|
||||
}) {
|
||||
continue;
|
||||
}
|
||||
let child = current_child.take().map(|mut child| child.kill());
|
||||
log::info!("Storybook changed, rebuilding...");
|
||||
current_child = Some(
|
||||
Command::new("cargo")
|
||||
.args(["run", "-p", "storybook"])
|
||||
.spawn()
|
||||
.ok()?,
|
||||
);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
let fs = Arc::new(fs::RealFs);
|
||||
|
||||
gpui2::App::new(Assets).unwrap().run(move |cx| {
|
||||
let mut store = SettingsStore::default();
|
||||
store
|
||||
|
@ -63,6 +96,10 @@ fn main() {
|
|||
})
|
||||
.and_then(|theme_name| theme_registry.get(&theme_name).ok());
|
||||
|
||||
cx.spawn(|_| async move {
|
||||
watch_zed_changes(fs).await;
|
||||
})
|
||||
.detach();
|
||||
cx.add_window(
|
||||
gpui2::WindowOptions {
|
||||
bounds: WindowBounds::Fixed(RectF::new(vec2f(0., 0.), vec2f(1700., 980.))),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue