feat: add new theme (#61)

Reviewed-on: #61
This commit was merged in pull request #61.
This commit is contained in:
2026-10-10 00:30:42 +00:00
parent 4ef764984b
commit 602a91b4f0
94 changed files with 3337 additions and 4456 deletions
+17 -16
View File
@@ -17,7 +17,7 @@ use gpui_base::dock::{
PaneRef, PanelId, TabGroupContext, TabGroupRenderer,
};
use gpui_base::{HandleEdge, Placement, ResizeHandleContext};
use theme::{ActiveTheme, TABBAR_HEIGHT};
use theme::{ActiveTheme, TABBAR_HEIGHT, TextStyle, Typeset as _, button_radius, panel_radius};
use crate::button::{Button, ButtonVariants as _};
use crate::resizable::{resize_handle, resize_handle_appearance};
@@ -83,9 +83,11 @@ pub fn add_panel_to(
window: &mut Window,
cx: &mut App,
) {
let _ = dock.update(cx, |area, cx| {
if let Err(error) = dock.update(cx, |area, cx| {
add_panel(area, panel, placement, window, cx);
});
}) {
log::warn!("Failed to add panel to dock: {error}");
}
}
/// The panel in any region of `area` whose logical id is `key`.
@@ -346,12 +348,12 @@ impl Render for DragPreview {
.justify_center()
.overflow_hidden()
.whitespace_nowrap()
.rounded(cx.theme().radius)
.text_sm()
.rounded(px(button_radius()))
.text_style(TextStyle::Callout)
.text_color(cx.theme().text)
.text_ellipsis()
.when(cx.theme().shadow, |this| this.shadow_xs())
.bg(cx.theme().background)
.bg(cx.theme().bg)
.child(panel_title(&self.panel, cx))
}
}
@@ -446,7 +448,7 @@ impl TabGroupSkin {
.flex_grow_1()
.min_w_16()
.when(droppable, |this| {
this.drag_over::<DragPanel>(|this, _, _, cx| this.bg(cx.theme().surface_background))
this.drag_over::<DragPanel>(|this, _, _, cx| this.bg(cx.theme().drop_target))
.on_drop({
let group = TabGroupContext::clone(group);
move |drag: &DragPanel, window, cx| {
@@ -465,7 +467,7 @@ impl TabGroupSkin {
let bar = TabBar::new("tab-bar")
.track_scroll(&self.scroll_handle)
.h(TABBAR_HEIGHT)
.bg(cx.theme().panel_background)
.bg(cx.theme().bg)
.when(needs_traffic_light_padding, |this| {
this.pl(px(TRAFFIC_LIGHT_PADDING))
})
@@ -537,7 +539,7 @@ impl TabGroupSkin {
this.rounded_l_none()
.border_l_2()
.border_r_0()
.border_color(cx.theme().border)
.border_color(cx.theme().drop_line)
})
.on_drop({
let group = TabGroupContext::clone(group);
@@ -567,7 +569,7 @@ impl TabGroupSkin {
h_flex()
.h(TABBAR_HEIGHT)
.w_full()
.bg(cx.theme().panel_background)
.bg(cx.theme().bg)
.child(bar.flex_1())
.child(window_controls())
.into_any_element()
@@ -670,8 +672,7 @@ impl TabGroupRenderer for TabGroupSkin {
window: &mut Window,
cx: &mut App,
) -> AnyElement {
// The left dock's only panel draws bare, so its content can own the
// window's top-left corner instead of a tab bar doing so.
// The plain left group draws bare so its content can own the window's top-left corner.
if self.is_plain_left_group(group, cx) {
return Empty.into_any_element();
}
@@ -717,7 +718,7 @@ impl TabGroupRenderer for TabGroupSkin {
.child(
div()
.size_full()
.bg(cx.theme().panel_background)
.bg(cx.theme().bg)
.overflow_hidden()
.child(panel.cached(StyleRefinement::default().v_flex().size_full())),
)
@@ -758,10 +759,10 @@ impl TabGroupRenderer for TabGroupSkin {
.top(top)
.w(width)
.h(height)
.rounded(cx.theme().radius_lg)
.rounded(px(panel_radius()))
.border_1()
.border_color(cx.theme().element_disabled)
.bg(cx.theme().drop_target_background)
.border_color(cx.theme().drop_line)
.bg(cx.theme().drop_target)
.into_any_element(),
)
}
+7 -56
View File
@@ -8,14 +8,9 @@ use gpui::{
use gpui_base::dock::{PanelId, PanelState};
use crate::button::Button;
use crate::menu::PopupMenu;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PanelEvent {
ZoomIn,
ZoomOut,
LayoutChanged,
}
pub enum PanelEvent {}
pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
/// The name of the panel used to serialize, deserialize and identify the panel.
@@ -31,44 +26,29 @@ pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
true
}
/// Return true if the panel is zoomable, default is `false`.
/// Whether the panel is zoomable, default is `true`.
fn zoomable(&self, _cx: &App) -> bool {
true
}
/// Return false to hide panel, true to show panel, default is `true`.
///
/// This method called in Panel render, we should make sure it is fast.
fn visible(&self, _cx: &App) -> bool {
true
}
/// Set active state of the panel.
///
/// This method will be called when the panel is active or inactive.
///
/// The last_active_panel and current_active_panel will be touched when the panel is active.
fn set_active(&self, _active: bool, _window: &mut Window, _cx: &mut App) {}
/// Set zoomed state of the panel.
///
/// This method will be called when the panel is zoomed or unzoomed.
///
/// Only current Panel will touch this method.
fn set_zoomed(&self, _zoomed: bool, _cx: &mut App) {}
/// The addition popup menu of the panel, default is `None`.
fn popup_menu(&self, this: PopupMenu, _cx: &App) -> PopupMenu {
this
}
/// The addition toolbar buttons of the panel used to show in the right of the title bar, default is `None`.
/// Toolbar buttons shown at the right of the title bar.
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
vec![]
}
}
pub trait PanelView: 'static + Send + Sync {
pub(crate) trait PanelView: 'static + Send + Sync {
fn panel_id(&self, cx: &App) -> SharedString;
fn title(&self, cx: &App) -> AnyElement;
fn closable(&self, cx: &App) -> bool;
@@ -76,8 +56,6 @@ pub trait PanelView: 'static + Send + Sync {
fn visible(&self, cx: &App) -> bool;
fn set_active(&self, active: bool, window: &mut Window, cx: &mut App);
fn set_zoomed(&self, zoomed: bool, cx: &mut App);
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu;
fn toolbar_buttons(&self, window: &Window, cx: &App) -> Vec<Button>;
fn view(&self) -> AnyView;
fn focus_handle(&self, cx: &App) -> FocusHandle;
}
@@ -115,14 +93,6 @@ impl<T: Panel> PanelView for Entity<T> {
})
}
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu {
self.read(cx).popup_menu(menu, cx)
}
fn toolbar_buttons(&self, window: &Window, cx: &App) -> Vec<Button> {
self.read(cx).toolbar_buttons(window, cx)
}
fn view(&self) -> AnyView {
self.clone().into()
}
@@ -132,24 +102,6 @@ impl<T: Panel> PanelView for Entity<T> {
}
}
impl From<&dyn PanelView> for AnyView {
fn from(handle: &dyn PanelView) -> Self {
handle.view()
}
}
impl<T: Panel> From<&dyn PanelView> for Entity<T> {
fn from(value: &dyn PanelView) -> Self {
value.view().downcast::<T>().unwrap()
}
}
impl PartialEq for dyn PanelView {
fn eq(&self, other: &Self) -> bool {
self.view() == other.view()
}
}
#[derive(Clone)]
pub struct PanelHandle {
id: PanelId,
@@ -164,13 +116,12 @@ impl PanelHandle {
}
}
/// Recover the coop handle behind one of base's.
pub fn of(panel: &Arc<dyn gpui_base::dock::PanelView>) -> Option<&Self> {
/// Downcast a base handle back to the coop handle.
pub(crate) fn of(panel: &Arc<dyn gpui_base::dock::PanelView>) -> Option<&Self> {
panel.as_any().downcast_ref::<Self>()
}
/// The coop panel behind this handle.
pub fn panel(&self) -> &Arc<dyn PanelView> {
pub(crate) fn panel(&self) -> &Arc<dyn PanelView> {
&self.panel
}
}