tiles: Add scrollbar_show option to Tiles (#1496)
This commit is contained in:
parent
b7815ed6ec
commit
fbaddbe9e3
3 changed files with 67 additions and 27 deletions
|
|
@ -7,6 +7,7 @@ use gpui_component::{
|
||||||
PanelState, PanelView, register_panel,
|
PanelState, PanelView, register_panel,
|
||||||
},
|
},
|
||||||
input::{Input, InputState},
|
input::{Input, InputState},
|
||||||
|
scroll::ScrollbarShow,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
@ -239,6 +240,17 @@ impl StoryTiles {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_scrollbar_show(dock_area: &mut DockArea, cx: &mut App) {
|
||||||
|
match dock_area.items() {
|
||||||
|
DockItem::Tiles { view, .. } => {
|
||||||
|
view.update(cx, |this, cx| {
|
||||||
|
this.set_scrollbar_show(Some(ScrollbarShow::Always), cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn load_tiles(
|
fn load_tiles(
|
||||||
dock_area: Entity<DockArea>,
|
dock_area: Entity<DockArea>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
|
|
@ -273,7 +285,7 @@ impl StoryTiles {
|
||||||
|
|
||||||
dock_area.update(cx, |dock_area, cx| {
|
dock_area.update(cx, |dock_area, cx| {
|
||||||
dock_area.load(state, window, cx).context("load layout")?;
|
dock_area.load(state, window, cx).context("load layout")?;
|
||||||
|
Self::set_scrollbar_show(dock_area, cx);
|
||||||
Ok::<(), anyhow::Error>(())
|
Ok::<(), anyhow::Error>(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -284,11 +296,12 @@ impl StoryTiles {
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
let dock_item = Self::init_default_layout(&dock_area, window, cx);
|
let dock_item = Self::init_default_layout(&dock_area, window, cx);
|
||||||
_ = dock_area.update(cx, |view, cx| {
|
_ = dock_area.update(cx, |dock_area, cx| {
|
||||||
view.set_version(TILES_DOCK_AREA.version, window, cx);
|
dock_area.set_version(TILES_DOCK_AREA.version, window, cx);
|
||||||
view.set_center(dock_item, window, cx);
|
dock_area.set_center(dock_item, window, cx);
|
||||||
|
|
||||||
Self::save_tiles(&view.dump(cx)).unwrap();
|
Self::set_scrollbar_show(dock_area, cx);
|
||||||
|
Self::save_tiles(&dock_area.dump(cx)).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use std::{
|
||||||
use crate::{
|
use crate::{
|
||||||
h_flex,
|
h_flex,
|
||||||
history::{History, HistoryItem},
|
history::{History, HistoryItem},
|
||||||
scroll::{Scrollbar, ScrollbarState},
|
scroll::{Scrollbar, ScrollbarShow, ScrollbarState},
|
||||||
v_flex, ActiveTheme, Icon, IconName,
|
v_flex, ActiveTheme, Icon, IconName,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -15,10 +15,11 @@ use super::{
|
||||||
DockArea, Panel, PanelEvent, PanelInfo, PanelState, PanelView, StackPanel, TabPanel, TileMeta,
|
DockArea, Panel, PanelEvent, PanelInfo, PanelState, PanelView, StackPanel, TabPanel, TileMeta,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, canvas, div, px, size, AnyElement, App, AppContext, Bounds, Context, DismissEvent,
|
actions, canvas, div, prelude::FluentBuilder, px, size, AnyElement, App, AppContext, Bounds,
|
||||||
DragMoveEvent, Empty, EntityId, EventEmitter, FocusHandle, Focusable, InteractiveElement,
|
Context, DismissEvent, DragMoveEvent, Empty, EntityId, EventEmitter, FocusHandle, Focusable,
|
||||||
IntoElement, MouseButton, MouseDownEvent, MouseUpEvent, ParentElement, Pixels, Point, Render,
|
InteractiveElement, IntoElement, MouseButton, MouseDownEvent, MouseUpEvent, ParentElement,
|
||||||
ScrollHandle, Size, StatefulInteractiveElement, Styled, WeakEntity, Window,
|
Pixels, Point, Render, ScrollHandle, Size, StatefulInteractiveElement, Styled, WeakEntity,
|
||||||
|
Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(tiles, [Undo, Redo]);
|
actions!(tiles, [Undo, Redo]);
|
||||||
|
|
@ -140,6 +141,7 @@ pub struct Tiles {
|
||||||
history: History<TileChange>,
|
history: History<TileChange>,
|
||||||
scroll_state: ScrollbarState,
|
scroll_state: ScrollbarState,
|
||||||
scroll_handle: ScrollHandle,
|
scroll_handle: ScrollHandle,
|
||||||
|
scrollbar_show: Option<ScrollbarShow>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Panel for Tiles {
|
impl Panel for Tiles {
|
||||||
|
|
@ -189,6 +191,7 @@ impl Tiles {
|
||||||
dragging_initial_mouse: Point::default(),
|
dragging_initial_mouse: Point::default(),
|
||||||
dragging_initial_bounds: Bounds::default(),
|
dragging_initial_bounds: Bounds::default(),
|
||||||
resizing_id: None,
|
resizing_id: None,
|
||||||
|
scrollbar_show: None,
|
||||||
resizing_drag_data: None,
|
resizing_drag_data: None,
|
||||||
bounds: Bounds::default(),
|
bounds: Bounds::default(),
|
||||||
history: History::new().group_interval(std::time::Duration::from_millis(100)),
|
history: History::new().group_interval(std::time::Duration::from_millis(100)),
|
||||||
|
|
@ -197,6 +200,16 @@ impl Tiles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the scrollbar show mode [`ScrollbarShow`], if not set use the `cx.theme().scrollbar_show`.
|
||||||
|
pub fn set_scrollbar_show(
|
||||||
|
&mut self,
|
||||||
|
scrollbar_show: Option<ScrollbarShow>,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
self.scrollbar_show = scrollbar_show;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn panels(&self) -> &[TileItem] {
|
pub fn panels(&self) -> &[TileItem] {
|
||||||
&self.panels
|
&self.panels
|
||||||
}
|
}
|
||||||
|
|
@ -1058,7 +1071,10 @@ impl Render for Tiles {
|
||||||
.bottom_0()
|
.bottom_0()
|
||||||
.child(
|
.child(
|
||||||
Scrollbar::both(&self.scroll_state, &self.scroll_handle)
|
Scrollbar::both(&self.scroll_state, &self.scroll_handle)
|
||||||
.scroll_size(scroll_size),
|
.scroll_size(scroll_size)
|
||||||
|
.when_some(self.scrollbar_show, |this, scrollbar_show| {
|
||||||
|
this.scrollbar_show(scrollbar_show)
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.size_full()
|
.size_full()
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ use std::{
|
||||||
|
|
||||||
use crate::{ActiveTheme, AxisExt};
|
use crate::{ActiveTheme, AxisExt};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
fill, point, px, relative, size, App, Axis, BorderStyle, Bounds, ContentMask, Corner,
|
fill, point, px, relative, size, App, Axis, BorderStyle, Bounds,
|
||||||
CursorStyle, Edges, Element, GlobalElementId, Hitbox, HitboxBehavior, Hsla, InspectorElementId,
|
ContentMask, Corner, CursorStyle, Edges, Element, GlobalElementId, Hitbox, HitboxBehavior,
|
||||||
IntoElement, IsZero, LayoutId, ListState, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
Hsla, InspectorElementId, IntoElement, IsZero, LayoutId, ListState, MouseDownEvent,
|
||||||
PaintQuad, Pixels, Point, Position, ScrollHandle, ScrollWheelEvent, Size, Style, Timer,
|
MouseMoveEvent, MouseUpEvent, PaintQuad, Pixels, Point, Position, ScrollHandle,
|
||||||
UniformListScrollHandle, Window,
|
ScrollWheelEvent, Size, Style, Timer, UniformListScrollHandle, Window,
|
||||||
};
|
};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -289,6 +289,7 @@ impl ScrollbarAxis {
|
||||||
/// Scrollbar control for scroll-area or a uniform-list.
|
/// Scrollbar control for scroll-area or a uniform-list.
|
||||||
pub struct Scrollbar {
|
pub struct Scrollbar {
|
||||||
axis: ScrollbarAxis,
|
axis: ScrollbarAxis,
|
||||||
|
scrollbar_show: Option<ScrollbarShow>,
|
||||||
scroll_handle: Rc<Box<dyn ScrollHandleOffsetable>>,
|
scroll_handle: Rc<Box<dyn ScrollHandleOffsetable>>,
|
||||||
state: ScrollbarState,
|
state: ScrollbarState,
|
||||||
scroll_size: Option<Size<Pixels>>,
|
scroll_size: Option<Size<Pixels>>,
|
||||||
|
|
@ -308,6 +309,7 @@ impl Scrollbar {
|
||||||
Self {
|
Self {
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
axis: axis.into(),
|
axis: axis.into(),
|
||||||
|
scrollbar_show: None,
|
||||||
scroll_handle: Rc::new(Box::new(scroll_handle.clone())),
|
scroll_handle: Rc::new(Box::new(scroll_handle.clone())),
|
||||||
max_fps: 120,
|
max_fps: 120,
|
||||||
scroll_size: None,
|
scroll_size: None,
|
||||||
|
|
@ -327,6 +329,12 @@ impl Scrollbar {
|
||||||
Self::new(ScrollbarAxis::Both, state, scroll_handle)
|
Self::new(ScrollbarAxis::Both, state, scroll_handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the scrollbar show mode [`ScrollbarShow`], if not set use the `cx.theme().scrollbar_show`.
|
||||||
|
pub fn scrollbar_show(mut self, scrollbar_show: ScrollbarShow) -> Self {
|
||||||
|
self.scrollbar_show = Some(scrollbar_show);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Create with horizontal scrollbar.
|
/// Create with horizontal scrollbar.
|
||||||
pub fn horizontal(
|
pub fn horizontal(
|
||||||
state: &ScrollbarState,
|
state: &ScrollbarState,
|
||||||
|
|
@ -408,8 +416,9 @@ impl Scrollbar {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_for_normal(cx: &App) -> (Hsla, Hsla, Hsla, Pixels, Pixels, Pixels) {
|
fn style_for_normal(&self, cx: &App) -> (Hsla, Hsla, Hsla, Pixels, Pixels, Pixels) {
|
||||||
let (width, inset, radius) = match cx.theme().scrollbar_show {
|
let scrollbar_show = self.scrollbar_show.unwrap_or(cx.theme().scrollbar_show);
|
||||||
|
let (width, inset, radius) = match scrollbar_show {
|
||||||
ScrollbarShow::Scrolling => (THUMB_WIDTH, THUMB_INSET, THUMB_RADIUS),
|
ScrollbarShow::Scrolling => (THUMB_WIDTH, THUMB_INSET, THUMB_RADIUS),
|
||||||
_ => (THUMB_ACTIVE_WIDTH, THUMB_ACTIVE_INSET, THUMB_ACTIVE_RADIUS),
|
_ => (THUMB_ACTIVE_WIDTH, THUMB_ACTIVE_INSET, THUMB_ACTIVE_RADIUS),
|
||||||
};
|
};
|
||||||
|
|
@ -424,8 +433,9 @@ impl Scrollbar {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_for_idle(cx: &App) -> (Hsla, Hsla, Hsla, Pixels, Pixels, Pixels) {
|
fn style_for_idle(&self, cx: &App) -> (Hsla, Hsla, Hsla, Pixels, Pixels, Pixels) {
|
||||||
let (width, inset, radius) = match cx.theme().scrollbar_show {
|
let scrollbar_show = self.scrollbar_show.unwrap_or(cx.theme().scrollbar_show);
|
||||||
|
let (width, inset, radius) = match scrollbar_show {
|
||||||
ScrollbarShow::Scrolling => (THUMB_WIDTH, THUMB_INSET, THUMB_RADIUS),
|
ScrollbarShow::Scrolling => (THUMB_WIDTH, THUMB_INSET, THUMB_RADIUS),
|
||||||
_ => (THUMB_ACTIVE_WIDTH, THUMB_ACTIVE_INSET, THUMB_ACTIVE_RADIUS),
|
_ => (THUMB_ACTIVE_WIDTH, THUMB_ACTIVE_INSET, THUMB_ACTIVE_RADIUS),
|
||||||
};
|
};
|
||||||
|
|
@ -577,9 +587,10 @@ impl Element for Scrollbar {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let scrollbar_show = self.scrollbar_show.unwrap_or(cx.theme().scrollbar_show);
|
||||||
let state = self.state.clone();
|
let state = self.state.clone();
|
||||||
let is_always_to_show = cx.theme().scrollbar_show.is_always();
|
let is_always_to_show = scrollbar_show.is_always();
|
||||||
let is_hover_to_show = cx.theme().scrollbar_show.is_hover();
|
let is_hover_to_show = scrollbar_show.is_hover();
|
||||||
let is_hovered_on_bar = state.get().hovered_axis == Some(axis);
|
let is_hovered_on_bar = state.get().hovered_axis == Some(axis);
|
||||||
let is_hovered_on_thumb = state.get().hovered_on_thumb == Some(axis);
|
let is_hovered_on_thumb = state.get().hovered_on_thumb == Some(axis);
|
||||||
let is_offset_changed = state.get().last_scroll_offset != self.scroll_handle.offset();
|
let is_offset_changed = state.get().last_scroll_offset != self.scroll_handle.offset();
|
||||||
|
|
@ -594,7 +605,7 @@ impl Element for Scrollbar {
|
||||||
Self::style_for_hovered_bar(cx)
|
Self::style_for_hovered_bar(cx)
|
||||||
}
|
}
|
||||||
} else if is_offset_changed {
|
} else if is_offset_changed {
|
||||||
Self::style_for_normal(cx)
|
self.style_for_normal(cx)
|
||||||
} else if is_always_to_show {
|
} else if is_always_to_show {
|
||||||
if is_hovered_on_thumb {
|
if is_hovered_on_thumb {
|
||||||
Self::style_for_hovered_thumb(cx)
|
Self::style_for_hovered_thumb(cx)
|
||||||
|
|
@ -602,7 +613,7 @@ impl Element for Scrollbar {
|
||||||
Self::style_for_hovered_bar(cx)
|
Self::style_for_hovered_bar(cx)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut idle_state = Self::style_for_idle(cx);
|
let mut idle_state = self.style_for_idle(cx);
|
||||||
// Delay 2s to fade out the scrollbar thumb (in 1s)
|
// Delay 2s to fade out the scrollbar thumb (in 1s)
|
||||||
if let Some(last_time) = state.get().last_scroll_time {
|
if let Some(last_time) = state.get().last_scroll_time {
|
||||||
let elapsed = Instant::now().duration_since(last_time).as_secs_f32();
|
let elapsed = Instant::now().duration_since(last_time).as_secs_f32();
|
||||||
|
|
@ -705,11 +716,11 @@ impl Element for Scrollbar {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) {
|
) {
|
||||||
|
let scrollbar_show = self.scrollbar_show.unwrap_or(cx.theme().scrollbar_show);
|
||||||
let view_id = window.current_view();
|
let view_id = window.current_view();
|
||||||
let hitbox_bounds = prepaint.hitbox.bounds;
|
let hitbox_bounds = prepaint.hitbox.bounds;
|
||||||
let is_visible =
|
let is_visible = self.state.get().is_scrollbar_visible() || scrollbar_show.is_always();
|
||||||
self.state.get().is_scrollbar_visible() || cx.theme().scrollbar_show.is_always();
|
let is_hover_to_show = scrollbar_show.is_hover();
|
||||||
let is_hover_to_show = cx.theme().scrollbar_show.is_hover();
|
|
||||||
|
|
||||||
// Update last_scroll_time when offset is changed.
|
// Update last_scroll_time when offset is changed.
|
||||||
if self.scroll_handle.offset() != self.state.get().last_scroll_offset {
|
if self.scroll_handle.offset() != self.state.get().last_scroll_offset {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue