panel: Support custom style for the panel title (#220)
This commit is contained in:
parent
e1d6b3aaed
commit
d6015f636c
4 changed files with 66 additions and 6 deletions
|
|
@ -94,6 +94,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -105,6 +106,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -116,6 +118,7 @@ impl StoryWorkspace {
|
|||
Some(Placement::Bottom),
|
||||
Some(px(200.)),
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -127,6 +130,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -138,6 +142,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -149,6 +154,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -160,6 +166,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -171,6 +178,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -182,6 +190,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -193,6 +202,7 @@ impl StoryWorkspace {
|
|||
Some(Placement::Bottom),
|
||||
Some(px(200.)),
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -204,6 +214,7 @@ impl StoryWorkspace {
|
|||
Some(Placement::Bottom),
|
||||
None,
|
||||
true,
|
||||
Some(cx.theme().muted),
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -223,6 +234,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -234,6 +246,7 @@ impl StoryWorkspace {
|
|||
Some(Placement::Bottom),
|
||||
Some(px(200.)),
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -245,6 +258,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -256,6 +270,7 @@ impl StoryWorkspace {
|
|||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
@ -267,6 +282,7 @@ impl StoryWorkspace {
|
|||
Some(Placement::Bottom),
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,17 +38,19 @@ pub use webview_story::WebViewStory;
|
|||
|
||||
use gpui::{
|
||||
actions, div, prelude::FluentBuilder as _, px, AnyView, AppContext, Div, EventEmitter,
|
||||
FocusableView, InteractiveElement, IntoElement, ParentElement, Pixels, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled as _, View, ViewContext, VisualContext, WindowContext,
|
||||
FocusableView, Hsla, InteractiveElement, IntoElement, ParentElement, Pixels, Render,
|
||||
SharedString, StatefulInteractiveElement, Styled as _, View, ViewContext, VisualContext,
|
||||
WindowContext,
|
||||
};
|
||||
|
||||
use ui::{
|
||||
divider::Divider,
|
||||
dock::{Panel, PanelEvent, TabPanel},
|
||||
dock::{Panel, PanelEvent, TabPanel, TitleStyle},
|
||||
h_flex,
|
||||
label::Label,
|
||||
notification::Notification,
|
||||
popup_menu::PopupMenu,
|
||||
theme::ActiveTheme,
|
||||
v_flex, ContextModal, Placement,
|
||||
};
|
||||
|
||||
|
|
@ -80,6 +82,7 @@ pub fn section(title: impl IntoElement, cx: &WindowContext) -> Div {
|
|||
pub struct StoryContainer {
|
||||
focus_handle: gpui::FocusHandle,
|
||||
name: SharedString,
|
||||
title_bg: Option<Hsla>,
|
||||
description: SharedString,
|
||||
width: Option<gpui::Pixels>,
|
||||
height: Option<gpui::Pixels>,
|
||||
|
|
@ -106,6 +109,7 @@ impl StoryContainer {
|
|||
Self {
|
||||
focus_handle,
|
||||
name: name.into(),
|
||||
title_bg: None,
|
||||
description: description.into(),
|
||||
width: None,
|
||||
height: None,
|
||||
|
|
@ -123,13 +127,18 @@ impl StoryContainer {
|
|||
placement: Option<Placement>,
|
||||
size: Option<Pixels>,
|
||||
closeable: bool,
|
||||
title_bg: Option<Hsla>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
let name = name.into();
|
||||
let description = description.into();
|
||||
|
||||
tab_panel.update(cx, |panel, cx| {
|
||||
let view = cx.new_view(|cx| Self::new(name, description, closeable, cx).story(story));
|
||||
let view = cx.new_view(|cx| {
|
||||
Self::new(name, description, closeable, cx)
|
||||
.story(story)
|
||||
.title_bg(title_bg)
|
||||
});
|
||||
if let Some(placement) = placement {
|
||||
panel.add_panel_at(Arc::new(view.clone()), placement, size, cx);
|
||||
} else {
|
||||
|
|
@ -154,6 +163,11 @@ impl StoryContainer {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn title_bg(mut self, title_bg: Option<Hsla>) -> Self {
|
||||
self.title_bg = title_bg;
|
||||
self
|
||||
}
|
||||
|
||||
fn on_action_panel_info(&mut self, _: &PanelInfo, cx: &mut ViewContext<Self>) {
|
||||
struct Info;
|
||||
let note = Notification::new(format!("You have clicked panel info on: {}", self.name))
|
||||
|
|
@ -167,6 +181,17 @@ impl Panel for StoryContainer {
|
|||
self.name.clone()
|
||||
}
|
||||
|
||||
fn title_style(&self, cx: &WindowContext) -> Option<TitleStyle> {
|
||||
if let Some(bg) = self.title_bg {
|
||||
Some(TitleStyle {
|
||||
background: bg,
|
||||
foreground: cx.theme().foreground,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn closeable(&self, _cx: &WindowContext) -> bool {
|
||||
self.closeable
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,26 @@
|
|||
use gpui::{AnyView, EventEmitter, FocusableView, SharedString, View, WindowContext};
|
||||
use gpui::{AnyView, EventEmitter, FocusableView, Hsla, SharedString, View, WindowContext};
|
||||
use rust_i18n::t;
|
||||
|
||||
use crate::popup_menu::PopupMenu;
|
||||
|
||||
use super::PanelEvent;
|
||||
|
||||
pub struct TitleStyle {
|
||||
pub background: Hsla,
|
||||
pub foreground: Hsla,
|
||||
}
|
||||
|
||||
pub trait Panel: EventEmitter<PanelEvent> + FocusableView {
|
||||
/// The title of the panel, default is `None`.
|
||||
fn title(&self, _cx: &WindowContext) -> SharedString {
|
||||
t!("Dock.Unnamed").into()
|
||||
}
|
||||
|
||||
/// The theme of the panel title, default is `None`.
|
||||
fn title_style(&self, _cx: &WindowContext) -> Option<TitleStyle> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Whether the panel can be closed, default is `true`.
|
||||
fn closeable(&self, _cx: &WindowContext) -> bool {
|
||||
true
|
||||
|
|
@ -23,9 +33,10 @@ pub trait Panel: EventEmitter<PanelEvent> + FocusableView {
|
|||
}
|
||||
|
||||
pub trait PanelView: 'static + Send + Sync {
|
||||
/// The title of the panel, default is `None`.
|
||||
fn title(&self, _cx: &WindowContext) -> SharedString;
|
||||
|
||||
fn title_style(&self, _cx: &WindowContext) -> Option<TitleStyle>;
|
||||
|
||||
fn closeable(&self, cx: &WindowContext) -> bool;
|
||||
|
||||
fn popup_menu(&self, menu: PopupMenu, cx: &WindowContext) -> PopupMenu;
|
||||
|
|
@ -38,6 +49,10 @@ impl<T: Panel> PanelView for View<T> {
|
|||
self.read(cx).title(cx)
|
||||
}
|
||||
|
||||
fn title_style(&self, cx: &WindowContext) -> Option<TitleStyle> {
|
||||
self.read(cx).title_style(cx)
|
||||
}
|
||||
|
||||
fn closeable(&self, cx: &WindowContext) -> bool {
|
||||
self.read(cx).closeable(cx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,12 +242,16 @@ impl TabPanel {
|
|||
if self.panels.len() == 1 {
|
||||
let panel = self.panels.get(0).unwrap();
|
||||
let title = panel.title(cx);
|
||||
let title_style = panel.title_style(cx);
|
||||
|
||||
return h_flex()
|
||||
.justify_between()
|
||||
.items_center()
|
||||
.line_height(rems(1.0))
|
||||
.pr_3()
|
||||
.when_some(title_style, |this, theme| {
|
||||
this.bg(theme.background).text_color(theme.foreground)
|
||||
})
|
||||
.child(
|
||||
div()
|
||||
.id("tab")
|
||||
|
|
|
|||
Loading…
Reference in a new issue