Detailed changes
@@ -300,11 +300,14 @@ impl TerminalView {
cx: &mut ViewContext<Self>,
) {
self.context_menu = Some(ContextMenu::build(cx, |menu, _| {
- menu.action(ListEntry::new(Label::new("Clear")), Box::new(Clear))
- .action(
- ListEntry::new(Label::new("Close")),
- Box::new(CloseActiveItem { save_intent: None }),
- )
+ menu.action(
+ ListEntry::new("clear", Label::new("Clear")),
+ Box::new(Clear),
+ )
+ .action(
+ ListEntry::new("close", Label::new("Close")),
+ Box::new(CloseActiveItem { save_intent: None }),
+ )
}));
dbg!(&position);
// todo!()
@@ -1,7 +1,7 @@
use std::cell::RefCell;
use std::rc::Rc;
-use crate::{prelude::*, v_stack, List, ListItem};
+use crate::{prelude::*, v_stack, List};
use crate::{ListEntry, ListSeparator, ListSubHeader};
use gpui::{
overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, DispatchPhase, Div,
@@ -9,7 +9,7 @@ use gpui::{
MouseDownEvent, Pixels, Point, Render, RenderOnce, View, VisualContext, WeakView,
};
-pub enum ContextMenuItem<V> {
+pub enum ContextMenuItem<V: 'static> {
Separator(ListSeparator),
Header(ListSubHeader),
Entry(
@@ -18,7 +18,7 @@ pub enum ContextMenuItem<V> {
),
}
-pub struct ContextMenu<V> {
+pub struct ContextMenu<V: 'static> {
items: Vec<ContextMenuItem<V>>,
focus_handle: FocusHandle,
handle: WeakView<V>,
@@ -105,25 +105,25 @@ impl<V: 'static> Render<Self> for ContextMenu<V> {
// .bg(cx.theme().colors().elevated_surface_background)
// .border()
// .border_color(cx.theme().colors().border)
- .child(List::new(
- self.items
- .iter()
- .map(|item| match item {
- ContextMenuItem::Separator(separator) => {
- ListItem::Separator(separator.clone())
- }
- ContextMenuItem::Header(header) => ListItem::Header(header.clone()),
- ContextMenuItem::Entry(entry, callback) => {
- let callback = callback.clone();
- let handle = self.handle.clone();
- ListItem::Entry(entry.clone().on_click(move |this, cx| {
+ .child(
+ List::new().children(self.items.iter().map(|item| match item {
+ ContextMenuItem::Separator(separator) => {
+ separator.clone().render_into_any()
+ }
+ ContextMenuItem::Header(header) => header.clone().render_into_any(),
+ ContextMenuItem::Entry(entry, callback) => {
+ let callback = callback.clone();
+ let handle = self.handle.clone();
+ entry
+ .clone()
+ .on_click(move |this, cx| {
handle.update(cx, |view, cx| callback(view, cx)).ok();
cx.emit(Manager::Dismiss);
- }))
- }
- })
- .collect(),
- )),
+ })
+ .render_into_any()
+ }
+ })),
+ ),
)
}
}
@@ -322,13 +322,17 @@ mod stories {
ContextMenu::build(cx, |menu, _| {
menu.header(header)
.separator()
- .entry(ListEntry::new(Label::new("Print current time")), |v, cx| {
- println!("dispatching PrintCurrentTime action");
- cx.dispatch_action(PrintCurrentDate.boxed_clone())
- })
- .entry(ListEntry::new(Label::new("Print best food")), |v, cx| {
- cx.dispatch_action(PrintBestFood.boxed_clone())
- })
+ .entry(
+ ListEntry::new("Print current time", Label::new("Print current time")),
+ |v, cx| {
+ println!("dispatching PrintCurrentTime action");
+ cx.dispatch_action(PrintCurrentDate.boxed_clone())
+ },
+ )
+ .entry(
+ ListEntry::new("Print best food", Label::new("Print best food")),
+ |v, cx| cx.dispatch_action(PrintBestFood.boxed_clone()),
+ )
})
}
@@ -1,4 +1,5 @@
-use gpui::{div, Div, RenderOnce, Stateful, StatefulInteractiveElement};
+use gpui::{div, AnyElement, Div, RenderOnce, Stateful, StatefulInteractiveElement};
+use smallvec::SmallVec;
use std::rc::Rc;
use crate::settings::user_settings;
@@ -177,7 +178,7 @@ impl ListHeader {
// }
}
-#[derive(Clone)]
+#[derive(RenderOnce, Clone)]
pub struct ListSubHeader {
label: SharedString,
left_icon: Option<Icon>,
@@ -197,8 +198,12 @@ impl ListSubHeader {
self.left_icon = left_icon;
self
}
+}
+
+impl<V: 'static> Component<V> for ListSubHeader {
+ type Rendered = Div<V>;
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
+ fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
h_stack().flex_1().w_full().relative().py_1().child(
div()
.h_6()
@@ -232,55 +237,9 @@ pub enum ListEntrySize {
Medium,
}
-#[derive(Clone)]
-pub enum ListItem<V: 'static> {
- Entry(ListEntry<V>),
- Separator(ListSeparator),
- Header(ListSubHeader),
-}
-
-impl<V: 'static> From<ListEntry<V>> for ListItem<V> {
- fn from(entry: ListEntry<V>) -> Self {
- Self::Entry(entry)
- }
-}
-
-impl<V: 'static> From<ListSeparator> for ListItem<V> {
- fn from(entry: ListSeparator) -> Self {
- Self::Separator(entry)
- }
-}
-
-impl<V: 'static> From<ListSubHeader> for ListItem<V> {
- fn from(entry: ListSubHeader) -> Self {
- Self::Header(entry)
- }
-}
-
-impl<V: 'static> ListItem<V> {
- pub fn new(label: Label) -> Self {
- Self::Entry(ListEntry::new(label))
- }
-
- pub fn as_entry(&mut self) -> Option<&mut ListEntry<V>> {
- if let Self::Entry(entry) = self {
- Some(entry)
- } else {
- None
- }
- }
-
- fn render(self, view: &mut V, ix: usize, cx: &mut ViewContext<V>) -> Div<V> {
- match self {
- ListItem::Entry(entry) => div().child(entry.render(ix, cx)),
- ListItem::Separator(separator) => div().child(separator.render(view, cx)),
- ListItem::Header(header) => div().child(header.render(view, cx)),
- }
- }
-}
-
-// #[derive(RenderOnce)]
-pub struct ListEntry<V> {
+#[derive(RenderOnce)]
+pub struct ListEntry<V: 'static> {
+ id: ElementId,
disabled: bool,
// TODO: Reintroduce this
// disclosure_control_style: DisclosureControlVisibility,
@@ -297,6 +256,7 @@ pub struct ListEntry<V> {
impl<V> Clone for ListEntry<V> {
fn clone(&self) -> Self {
Self {
+ id: self.id.clone(),
disabled: self.disabled,
indent_level: self.indent_level,
label: self.label.clone(),
@@ -311,8 +271,9 @@ impl<V> Clone for ListEntry<V> {
}
impl<V: 'static> ListEntry<V> {
- pub fn new(label: Label) -> Self {
+ pub fn new(id: impl Into<ElementId>, label: Label) -> Self {
Self {
+ id: id.into(),
disabled: false,
indent_level: 0,
label,
@@ -364,8 +325,12 @@ impl<V: 'static> ListEntry<V> {
self.size = size;
self
}
+}
+
+impl<V: 'static> Component<V> for ListEntry<V> {
+ type Rendered = Stateful<V, Div<V>>;
- fn render(self, ix: usize, cx: &mut ViewContext<V>) -> Stateful<V, Div<V>> {
+ fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
let settings = user_settings(cx);
let left_content = match self.left_slot.clone() {
@@ -386,7 +351,7 @@ impl<V: 'static> ListEntry<V> {
ListEntrySize::Medium => div().h_7(),
};
div()
- .id(ix)
+ .id(self.id)
.relative()
.hover(|mut style| {
style.background = Some(cx.theme().colors().editor_background.into());
@@ -454,25 +419,20 @@ impl<V: 'static> Component<V> for ListSeparator {
#[derive(RenderOnce)]
pub struct List<V: 'static> {
- items: Vec<ListItem<V>>,
/// Message to display when the list is empty
/// Defaults to "No items"
empty_message: SharedString,
header: Option<ListHeader>,
toggle: Toggle,
+ children: SmallVec<[AnyElement<V>; 2]>,
}
impl<V: 'static> Component<V> for List<V> {
type Rendered = Div<V>;
fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
- let list_content = match (self.items.is_empty(), self.toggle) {
- (false, _) => div().children(
- self.items
- .into_iter()
- .enumerate()
- .map(|(ix, item)| item.render(view, ix, cx)),
- ),
+ let list_content = match (self.children.is_empty(), self.toggle) {
+ (false, _) => div().children(self.children),
(true, Toggle::Toggled(false)) => div(),
(true, _) => {
div().child(Label::new(self.empty_message.clone()).color(TextColor::Muted))
@@ -488,12 +448,12 @@ impl<V: 'static> Component<V> for List<V> {
}
impl<V: 'static> List<V> {
- pub fn new(items: Vec<ListItem<V>>) -> Self {
+ pub fn new() -> Self {
Self {
- items,
empty_message: "No items".into(),
header: None,
toggle: Toggle::NotToggleable,
+ children: SmallVec::new(),
}
}
@@ -511,25 +471,10 @@ impl<V: 'static> List<V> {
self.toggle = toggle;
self
}
+}
- fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
- let list_content = match (self.items.is_empty(), self.toggle) {
- (false, _) => div().children(
- self.items
- .into_iter()
- .enumerate()
- .map(|(ix, item)| item.render(view, ix, cx)),
- ),
- (true, Toggle::Toggled(false)) => div(),
- (true, _) => {
- div().child(Label::new(self.empty_message.clone()).color(TextColor::Muted))
- }
- };
-
- v_stack()
- .w_full()
- .py_1()
- .children(self.header.map(|header| header))
- .child(list_content)
+impl<V: 'static> ParentElement<V> for List<V> {
+ fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
+ &mut self.children
}
}
@@ -7,14 +7,13 @@ use gpui::{AppContext, ViewContext};
use rand::Rng;
use theme2::ActiveTheme;
-use crate::{binding, HighlightedText};
use crate::{
- Buffer, BufferRow, BufferRows, Button, EditorPane, FileSystemStatus, GitStatus,
- HighlightedLine, Icon, KeyBinding, Label, ListEntry, ListEntrySize, Livestream, MicStatus,
- Notification, PaletteItem, Player, PlayerCallStatus, PlayerWithCallStatus, PublicPlayer,
- ScreenShareStatus, Symbol, Tab, TextColor, Toggle, VideoStatus,
+ binding, Buffer, BufferRow, BufferRows, Button, EditorPane, FileSystemStatus, GitStatus,
+ HighlightedLine, HighlightedText, Icon, KeyBinding, Label, ListEntry, ListEntrySize,
+ Livestream, MicStatus, Notification, NotificationAction, PaletteItem, Player, PlayerCallStatus,
+ PlayerWithCallStatus, PublicPlayer, ScreenShareStatus, Symbol, Tab, TextColor, Toggle,
+ VideoStatus,
};
-use crate::{ListItem, NotificationAction};
pub fn static_tabs_example() -> Vec<Tab> {
vec![
@@ -478,225 +477,238 @@ pub fn static_new_notification_items_2<V: 'static>() -> Vec<Notification<V>> {
]
}
-pub fn static_project_panel_project_items<V>() -> Vec<ListItem<V>> {
+pub fn static_project_panel_project_items<V>() -> Vec<ListEntry<V>> {
vec![
- ListEntry::new(Label::new("zed"))
+ ListEntry::new("zed", Label::new("zed"))
.left_icon(Icon::FolderOpen.into())
.indent_level(0)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new(".cargo"))
+ ListEntry::new(".cargo", Label::new(".cargo"))
.left_icon(Icon::Folder.into())
.indent_level(1),
- ListEntry::new(Label::new(".config"))
+ ListEntry::new(".config", Label::new(".config"))
.left_icon(Icon::Folder.into())
.indent_level(1),
- ListEntry::new(Label::new(".git").color(TextColor::Hidden))
+ ListEntry::new(".git", Label::new(".git").color(TextColor::Hidden))
.left_icon(Icon::Folder.into())
.indent_level(1),
- ListEntry::new(Label::new(".cargo"))
+ ListEntry::new(".cargo", Label::new(".cargo"))
.left_icon(Icon::Folder.into())
.indent_level(1),
- ListEntry::new(Label::new(".idea").color(TextColor::Hidden))
+ ListEntry::new(".idea", Label::new(".idea").color(TextColor::Hidden))
.left_icon(Icon::Folder.into())
.indent_level(1),
- ListEntry::new(Label::new("assets"))
+ ListEntry::new("assets", Label::new("assets"))
.left_icon(Icon::Folder.into())
.indent_level(1)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("cargo-target").color(TextColor::Hidden))
- .left_icon(Icon::Folder.into())
- .indent_level(1),
- ListEntry::new(Label::new("crates"))
+ ListEntry::new(
+ "cargo-target",
+ Label::new("cargo-target").color(TextColor::Hidden),
+ )
+ .left_icon(Icon::Folder.into())
+ .indent_level(1),
+ ListEntry::new("crates", Label::new("crates"))
.left_icon(Icon::FolderOpen.into())
.indent_level(1)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("activity_indicator"))
+ ListEntry::new("activity_indicator", Label::new("activity_indicator"))
.left_icon(Icon::Folder.into())
.indent_level(2),
- ListEntry::new(Label::new("ai"))
+ ListEntry::new("ai", Label::new("ai"))
.left_icon(Icon::Folder.into())
.indent_level(2),
- ListEntry::new(Label::new("audio"))
+ ListEntry::new("audio", Label::new("audio"))
.left_icon(Icon::Folder.into())
.indent_level(2),
- ListEntry::new(Label::new("auto_update"))
+ ListEntry::new("auto_update", Label::new("auto_update"))
.left_icon(Icon::Folder.into())
.indent_level(2),
- ListEntry::new(Label::new("breadcrumbs"))
+ ListEntry::new("breadcrumbs", Label::new("breadcrumbs"))
.left_icon(Icon::Folder.into())
.indent_level(2),
- ListEntry::new(Label::new("call"))
+ ListEntry::new("call", Label::new("call"))
.left_icon(Icon::Folder.into())
.indent_level(2),
- ListEntry::new(Label::new("sqlez").color(TextColor::Modified))
+ ListEntry::new("sqlez", Label::new("sqlez").color(TextColor::Modified))
.left_icon(Icon::Folder.into())
.indent_level(2)
.toggle(Toggle::Toggled(false)),
- ListEntry::new(Label::new("gpui2"))
+ ListEntry::new("gpui2", Label::new("gpui2"))
.left_icon(Icon::FolderOpen.into())
.indent_level(2)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("src"))
+ ListEntry::new("src", Label::new("src"))
.left_icon(Icon::FolderOpen.into())
.indent_level(3)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("derive_element.rs"))
+ ListEntry::new("derive_element.rs", Label::new("derive_element.rs"))
.left_icon(Icon::FileRust.into())
.indent_level(4),
- ListEntry::new(Label::new("storybook").color(TextColor::Modified))
- .left_icon(Icon::FolderOpen.into())
- .indent_level(1)
- .toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("docs").color(TextColor::Default))
+ ListEntry::new(
+ "storybook",
+ Label::new("storybook").color(TextColor::Modified),
+ )
+ .left_icon(Icon::FolderOpen.into())
+ .indent_level(1)
+ .toggle(Toggle::Toggled(true)),
+ ListEntry::new("docs", Label::new("docs").color(TextColor::Default))
.left_icon(Icon::Folder.into())
.indent_level(2)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("src").color(TextColor::Modified))
+ ListEntry::new("src", Label::new("src").color(TextColor::Modified))
.left_icon(Icon::FolderOpen.into())
.indent_level(3)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("ui").color(TextColor::Modified))
+ ListEntry::new("ui", Label::new("ui").color(TextColor::Modified))
.left_icon(Icon::FolderOpen.into())
.indent_level(4)
.toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("component").color(TextColor::Created))
- .left_icon(Icon::FolderOpen.into())
- .indent_level(5)
- .toggle(Toggle::Toggled(true)),
- ListEntry::new(Label::new("facepile.rs").color(TextColor::Default))
- .left_icon(Icon::FileRust.into())
- .indent_level(6),
- ListEntry::new(Label::new("follow_group.rs").color(TextColor::Default))
+ ListEntry::new(
+ "component",
+ Label::new("component").color(TextColor::Created),
+ )
+ .left_icon(Icon::FolderOpen.into())
+ .indent_level(5)
+ .toggle(Toggle::Toggled(true)),
+ ListEntry::new(
+ "facepile.rs",
+ Label::new("facepile.rs").color(TextColor::Default),
+ )
+ .left_icon(Icon::FileRust.into())
+ .indent_level(6),
+ ListEntry::new(
+ "follow_group.rs",
+ Label::new("follow_group.rs").color(TextColor::Default),
+ )
+ .left_icon(Icon::FileRust.into())
+ .indent_level(6),
+ ListEntry::new(
+ "list_item.rs",
+ Label::new("list_item.rs").color(TextColor::Created),
+ )
+ .left_icon(Icon::FileRust.into())
+ .indent_level(6),
+ ListEntry::new("tab.rs", Label::new("tab.rs").color(TextColor::Default))
.left_icon(Icon::FileRust.into())
.indent_level(6),
- ListEntry::new(Label::new("list_item.rs").color(TextColor::Created))
- .left_icon(Icon::FileRust.into())
- .indent_level(6),
- ListEntry::new(Label::new("tab.rs").color(TextColor::Default))
- .left_icon(Icon::FileRust.into())
- .indent_level(6),
- ListEntry::new(Label::new("target").color(TextColor::Hidden))
+ ListEntry::new("target", Label::new("target").color(TextColor::Hidden))
.left_icon(Icon::Folder.into())
.indent_level(1),
- ListEntry::new(Label::new(".dockerignore"))
+ ListEntry::new(".dockerignore", Label::new(".dockerignore"))
.left_icon(Icon::FileGeneric.into())
.indent_level(1),
- ListEntry::new(Label::new(".DS_Store").color(TextColor::Hidden))
- .left_icon(Icon::FileGeneric.into())
- .indent_level(1),
- ListEntry::new(Label::new("Cargo.lock"))
+ ListEntry::new(
+ ".DS_Store",
+ Label::new(".DS_Store").color(TextColor::Hidden),
+ )
+ .left_icon(Icon::FileGeneric.into())
+ .indent_level(1),
+ ListEntry::new("Cargo.lock", Label::new("Cargo.lock"))
.left_icon(Icon::FileLock.into())
.indent_level(1),
- ListEntry::new(Label::new("Cargo.toml"))
+ ListEntry::new("Cargo.toml", Label::new("Cargo.toml"))
.left_icon(Icon::FileToml.into())
.indent_level(1),
- ListEntry::new(Label::new("Dockerfile"))
+ ListEntry::new("Dockerfile", Label::new("Dockerfile"))
.left_icon(Icon::FileGeneric.into())
.indent_level(1),
- ListEntry::new(Label::new("Procfile"))
+ ListEntry::new("Procfile", Label::new("Procfile"))
.left_icon(Icon::FileGeneric.into())
.indent_level(1),
- ListEntry::new(Label::new("README.md"))
+ ListEntry::new("README.md", Label::new("README.md"))
.left_icon(Icon::FileDoc.into())
.indent_level(1),
]
- .into_iter()
- .map(From::from)
- .collect()
}
-pub fn static_project_panel_single_items<V>() -> Vec<ListItem<V>> {
+pub fn static_project_panel_single_items<V>() -> Vec<ListEntry<V>> {
vec![
- ListEntry::new(Label::new("todo.md"))
+ ListEntry::new("todo.md", Label::new("todo.md"))
.left_icon(Icon::FileDoc.into())
.indent_level(0),
- ListEntry::new(Label::new("README.md"))
+ ListEntry::new("README.md", Label::new("README.md"))
.left_icon(Icon::FileDoc.into())
.indent_level(0),
- ListEntry::new(Label::new("config.json"))
+ ListEntry::new("config.json", Label::new("config.json"))
.left_icon(Icon::FileGeneric.into())
.indent_level(0),
]
- .into_iter()
- .map(From::from)
- .collect()
}
-pub fn static_collab_panel_current_call<V>() -> Vec<ListItem<V>> {
+pub fn static_collab_panel_current_call<V>() -> Vec<ListEntry<V>> {
vec![
- ListEntry::new(Label::new("as-cii")).left_avatar("http://github.com/as-cii.png?s=50"),
- ListEntry::new(Label::new("nathansobo"))
+ ListEntry::new("as-cii", Label::new("as-cii"))
+ .left_avatar("http://github.com/as-cii.png?s=50"),
+ ListEntry::new("nathansobo", Label::new("nathansobo"))
.left_avatar("http://github.com/nathansobo.png?s=50"),
- ListEntry::new(Label::new("maxbrunsfeld"))
+ ListEntry::new("maxbrunsfeld", Label::new("maxbrunsfeld"))
.left_avatar("http://github.com/maxbrunsfeld.png?s=50"),
]
- .into_iter()
- .map(From::from)
- .collect()
}
-pub fn static_collab_panel_channels<V>() -> Vec<ListItem<V>> {
+pub fn static_collab_panel_channels<V>() -> Vec<ListEntry<V>> {
vec![
- ListEntry::new(Label::new("zed"))
+ ListEntry::new("zed", Label::new("zed"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(0),
- ListEntry::new(Label::new("community"))
+ ListEntry::new("community", Label::new("community"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(1),
- ListEntry::new(Label::new("dashboards"))
- .left_icon(Icon::Hash.into())
- .size(ListEntrySize::Medium)
- .indent_level(2),
- ListEntry::new(Label::new("feedback"))
+ ListEntry::new("dashboards", Label::new("dashboards"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("teams-in-channels-alpha"))
+ ListEntry::new("feedback", Label::new("feedback"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("current-projects"))
+ ListEntry::new(
+ "teams-in-channels-alpha",
+ Label::new("teams-in-channels-alpha"),
+ )
+ .left_icon(Icon::Hash.into())
+ .size(ListEntrySize::Medium)
+ .indent_level(2),
+ ListEntry::new("current-projects", Label::new("current-projects"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(1),
- ListEntry::new(Label::new("codegen"))
+ ListEntry::new("codegen", Label::new("codegen"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("gpui2"))
+ ListEntry::new("gpui2", Label::new("gpui2"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("livestreaming"))
+ ListEntry::new("livestreaming", Label::new("livestreaming"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("open-source"))
+ ListEntry::new("open-source", Label::new("open-source"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("replace"))
+ ListEntry::new("replace", Label::new("replace"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("semantic-index"))
+ ListEntry::new("semantic-index", Label::new("semantic-index"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("vim"))
+ ListEntry::new("vim", Label::new("vim"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
- ListEntry::new(Label::new("web-tech"))
+ ListEntry::new("web-tech", Label::new("web-tech"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
]
- .into_iter()
- .map(From::from)
- .collect()
}
pub fn example_editor_actions() -> Vec<PaletteItem> {
@@ -28,41 +28,45 @@ impl<V: 'static> Component<V> for CollabPanel {
.border_color(cx.theme().colors().border)
.border_b()
.child(
- List::new(static_collab_panel_current_call())
+ List::new()
.header(
ListHeader::new("CRDB")
.left_icon(Icon::Hash.into())
.toggle(Toggle::Toggled(true)),
)
- .toggle(Toggle::Toggled(true)),
+ .toggle(Toggle::Toggled(true))
+ .children(static_collab_panel_current_call()),
),
)
.child(
v_stack().id("channels").py_1().child(
- List::new(static_collab_panel_channels())
+ List::new()
.header(ListHeader::new("CHANNELS").toggle(Toggle::Toggled(true)))
.empty_message("No channels yet. Add a channel to get started.")
- .toggle(Toggle::Toggled(true)),
+ .toggle(Toggle::Toggled(true))
+ .children(static_collab_panel_channels()),
),
)
.child(
v_stack().id("contacts-online").py_1().child(
- List::new(static_collab_panel_current_call())
+ List::new()
.header(
ListHeader::new("CONTACTS – ONLINE")
.toggle(Toggle::Toggled(true)),
)
- .toggle(Toggle::Toggled(true)),
+ .toggle(Toggle::Toggled(true))
+ .children(static_collab_panel_current_call()),
),
)
.child(
v_stack().id("contacts-offline").py_1().child(
- List::new(static_collab_panel_current_call())
+ List::new()
.header(
ListHeader::new("CONTACTS – OFFLINE")
.toggle(Toggle::Toggled(false)),
)
- .toggle(Toggle::Toggled(false)),
+ .toggle(Toggle::Toggled(false))
+ .children(static_collab_panel_current_call()),
),
),
)
@@ -29,14 +29,16 @@ impl<V: 'static> Component<V> for ProjectPanel {
.flex_col()
.overflow_y_scroll()
.child(
- List::new(static_project_panel_single_items())
+ List::new()
.header(ListHeader::new("FILES"))
- .empty_message("No files in directory"),
+ .empty_message("No files in directory")
+ .children(static_project_panel_single_items()),
)
.child(
- List::new(static_project_panel_project_items())
+ List::new()
.header(ListHeader::new("PROJECT"))
- .empty_message("No folders in directory"),
+ .empty_message("No folders in directory")
+ .children(static_project_panel_project_items()),
),
)
.child(
@@ -67,14 +69,16 @@ impl ProjectPanel {
.flex_col()
.overflow_y_scroll()
.child(
- List::new(static_project_panel_single_items())
+ List::new()
.header(ListHeader::new("FILES"))
- .empty_message("No files in directory"),
+ .empty_message("No files in directory")
+ .children(static_project_panel_single_items()),
)
.child(
- List::new(static_project_panel_project_items())
+ List::new()
.header(ListHeader::new("PROJECT"))
- .empty_message("No folders in directory"),
+ .empty_message("No folders in directory")
+ .children(static_project_panel_project_items()),
),
)
.child(
@@ -719,10 +719,10 @@ impl Render<Self> for PanelButtons {
{
let panel = panel.clone();
menu = menu.entry(
- ListEntry::new(Label::new(format!(
- "Dock {}",
- position.to_label()
- ))),
+ ListEntry::new(
+ SharedString::from(format!("dock-{position:?}")),
+ Label::new(format!("Dock {}", position.to_label())),
+ ),
move |_, cx| {
panel.set_position(position, cx);
},