Restructure Pane to have a single Toolbar with multiple items

This commit is contained in:
Antonio Scandurra 2022-03-29 11:48:21 +02:00
parent d296bb21a8
commit 9df2dacd85
9 changed files with 318 additions and 264 deletions

View file

@ -0,0 +1,131 @@
use crate::{ItemHandle, Settings};
use gpui::{
elements::*, AnyViewHandle, ElementBox, Entity, MutableAppContext, RenderContext, View,
ViewContext, ViewHandle,
};
pub trait ToolbarItemView: View {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn crate::ItemHandle>,
cx: &mut ViewContext<Self>,
);
}
trait ToolbarItemViewHandle {
fn to_any(&self) -> AnyViewHandle;
fn set_active_pane_item(
&self,
active_pane_item: Option<&dyn ItemHandle>,
cx: &mut MutableAppContext,
);
}
pub struct Toolbar {
active_pane_item: Option<Box<dyn ItemHandle>>,
left_items: Vec<Box<dyn ToolbarItemViewHandle>>,
right_items: Vec<Box<dyn ToolbarItemViewHandle>>,
}
impl Entity for Toolbar {
type Event = ();
}
impl View for Toolbar {
fn ui_name() -> &'static str {
"Toolbar"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.workspace.toolbar;
Flex::row()
.with_children(self.left_items.iter().map(|i| {
ChildView::new(i.as_ref())
.aligned()
.contained()
.with_margin_right(theme.item_spacing)
.boxed()
}))
.with_child(Empty::new().flexible(1., true).boxed())
.with_children(self.right_items.iter().map(|i| {
ChildView::new(i.as_ref())
.aligned()
.contained()
.with_margin_left(theme.item_spacing)
.boxed()
}))
.contained()
.with_style(theme.container)
.constrained()
.with_height(theme.height)
.boxed()
}
}
impl Toolbar {
pub fn new() -> Self {
Self {
active_pane_item: None,
left_items: Default::default(),
right_items: Default::default(),
}
}
pub fn add_left_item<T>(&mut self, item: ViewHandle<T>, cx: &mut ViewContext<Self>)
where
T: 'static + ToolbarItemView,
{
item.set_active_pane_item(self.active_pane_item.as_deref(), cx);
self.left_items.push(Box::new(item));
cx.notify();
}
pub fn add_right_item<T>(&mut self, item: ViewHandle<T>, cx: &mut ViewContext<Self>)
where
T: 'static + ToolbarItemView,
{
item.set_active_pane_item(self.active_pane_item.as_deref(), cx);
self.right_items.push(Box::new(item));
cx.notify();
}
pub fn set_active_pane_item(
&mut self,
item: Option<&dyn ItemHandle>,
cx: &mut ViewContext<Self>,
) {
self.active_pane_item = item.map(|item| item.boxed_clone());
for tool in self.left_items.iter().chain(&self.right_items) {
tool.set_active_pane_item(item, cx);
}
}
pub fn item_of_type<T: ToolbarItemView>(&self) -> Option<ViewHandle<T>> {
self.left_items
.iter()
.chain(&self.right_items)
.find_map(|tool| tool.to_any().downcast())
}
}
impl<T: ToolbarItemView> ToolbarItemViewHandle for ViewHandle<T> {
fn to_any(&self) -> AnyViewHandle {
self.into()
}
fn set_active_pane_item(
&self,
active_pane_item: Option<&dyn ItemHandle>,
cx: &mut MutableAppContext,
) {
self.update(cx, |this, cx| {
this.set_active_pane_item(active_pane_item, cx)
});
}
}
impl Into<AnyViewHandle> for &dyn ToolbarItemViewHandle {
fn into(self) -> AnyViewHandle {
self.to_any()
}
}