chore: improve tab component
This commit is contained in:
50
Cargo.lock
generated
50
Cargo.lock
generated
@@ -807,9 +807,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.11"
|
version = "1.2.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4730490333d58093109dc02c23174c3f4d490998c3fed3cc8e82d57afedb9cf"
|
checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1039,7 +1039,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collections"
|
name = "collections"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"rustc-hash 2.1.0",
|
"rustc-hash 2.1.0",
|
||||||
@@ -1346,7 +1346,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_refineable"
|
name = "derive_refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2059,7 +2059,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui"
|
name = "gpui"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"as-raw-xcb-connection",
|
"as-raw-xcb-connection",
|
||||||
@@ -2146,7 +2146,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_macros"
|
name = "gpui_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2156,7 +2156,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_tokio"
|
name = "gpui_tokio"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gpui",
|
"gpui",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -2361,7 +2361,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "http_client"
|
name = "http_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2851,7 +2851,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3012,7 +3012,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "media"
|
name = "media"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bindgen",
|
"bindgen",
|
||||||
@@ -3191,7 +3191,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr"
|
name = "nostr"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#dda112c89422cda6740fdae404e09a227a0f79ce"
|
source = "git+https://github.com/rust-nostr/nostr#e57c6e3733de2799294bd70bf325aaf08a60e4d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -3219,7 +3219,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-connect"
|
name = "nostr-connect"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#dda112c89422cda6740fdae404e09a227a0f79ce"
|
source = "git+https://github.com/rust-nostr/nostr#e57c6e3733de2799294bd70bf325aaf08a60e4d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"nostr",
|
"nostr",
|
||||||
@@ -3231,7 +3231,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-database"
|
name = "nostr-database"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#dda112c89422cda6740fdae404e09a227a0f79ce"
|
source = "git+https://github.com/rust-nostr/nostr#e57c6e3733de2799294bd70bf325aaf08a60e4d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"flatbuffers",
|
"flatbuffers",
|
||||||
"nostr",
|
"nostr",
|
||||||
@@ -3241,7 +3241,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-lmdb"
|
name = "nostr-lmdb"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#dda112c89422cda6740fdae404e09a227a0f79ce"
|
source = "git+https://github.com/rust-nostr/nostr#e57c6e3733de2799294bd70bf325aaf08a60e4d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"heed",
|
"heed",
|
||||||
@@ -3252,7 +3252,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-relay-pool"
|
name = "nostr-relay-pool"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#dda112c89422cda6740fdae404e09a227a0f79ce"
|
source = "git+https://github.com/rust-nostr/nostr#e57c6e3733de2799294bd70bf325aaf08a60e4d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"async-wsocket",
|
"async-wsocket",
|
||||||
@@ -3268,7 +3268,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-sdk"
|
name = "nostr-sdk"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#dda112c89422cda6740fdae404e09a227a0f79ce"
|
source = "git+https://github.com/rust-nostr/nostr#e57c6e3733de2799294bd70bf325aaf08a60e4d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"nostr",
|
"nostr",
|
||||||
@@ -4276,7 +4276,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "refineable"
|
name = "refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_refineable",
|
"derive_refineable",
|
||||||
]
|
]
|
||||||
@@ -4405,7 +4405,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest_client"
|
name = "reqwest_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -4755,7 +4755,7 @@ checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "semantic_version"
|
name = "semantic_version"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -5080,7 +5080,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sum_tree"
|
name = "sum_tree"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"log",
|
"log",
|
||||||
@@ -5902,7 +5902,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "util"
|
name = "util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#28b80455f97dbe21d5d9845b85928feca652c518"
|
source = "git+https://github.com/zed-industries/zed#0963401a8d0e7afed461090cb57be8047e1f79c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-fs",
|
"async-fs",
|
||||||
@@ -5927,11 +5927,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.12.1"
|
version = "1.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
|
checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.2.15",
|
"getrandom 0.3.1",
|
||||||
"serde",
|
"serde",
|
||||||
"sha1_smol",
|
"sha1_smol",
|
||||||
]
|
]
|
||||||
@@ -6287,7 +6287,7 @@ version = "0.1.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ use crate::{
|
|||||||
AxisExt as _, StyledExt,
|
AxisExt as _, StyledExt,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, prelude::FluentBuilder as _, px, App, AppContext, Axis, Context, Element, Entity,
|
div, prelude::FluentBuilder as _, px, AnyView, App, AppContext, Axis, Context, Element, Entity,
|
||||||
InteractiveElement as _, IntoElement, MouseMoveEvent, MouseUpEvent, ParentElement as _, Pixels,
|
InteractiveElement as _, IntoElement, MouseMoveEvent, MouseUpEvent, ParentElement as _, Pixels,
|
||||||
Point, Render, StatefulInteractiveElement, Style, Styled as _, WeakEntity, Window,
|
Point, Render, StatefulInteractiveElement, Style, StyleRefinement, Styled as _, WeakEntity,
|
||||||
|
Window,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -355,6 +356,8 @@ impl Render for Dock {
|
|||||||
return div();
|
return div();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cache_style = StyleRefinement::default().v_flex().size_full();
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.relative()
|
.relative()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
@@ -369,8 +372,10 @@ impl Render for Dock {
|
|||||||
})
|
})
|
||||||
.map(|this| match &self.panel {
|
.map(|this| match &self.panel {
|
||||||
DockItem::Split { view, .. } => this.child(view.clone()),
|
DockItem::Split { view, .. } => this.child(view.clone()),
|
||||||
DockItem::Tabs { view, .. } => this.child(view.clone()),
|
DockItem::Tabs { view, .. } => {
|
||||||
DockItem::Panel { view, .. } => this.child(view.clone().view()),
|
this.child(AnyView::from(view.clone()).cached(cache_style))
|
||||||
|
}
|
||||||
|
DockItem::Panel { view, .. } => this.child(view.clone().view().cached(cache_style)),
|
||||||
})
|
})
|
||||||
.child(self.render_resize_handle(window, cx))
|
.child(self.render_resize_handle(window, cx))
|
||||||
.child(DockElement {
|
.child(DockElement {
|
||||||
|
|||||||
@@ -51,6 +51,27 @@ pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
|
|||||||
true
|
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, _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`.
|
/// The addition popup menu of the panel, default is `None`.
|
||||||
fn popup_menu(&self, this: PopupMenu, _cx: &App) -> PopupMenu {
|
fn popup_menu(&self, this: PopupMenu, _cx: &App) -> PopupMenu {
|
||||||
this
|
this
|
||||||
@@ -68,6 +89,9 @@ pub trait PanelView: 'static + Send + Sync {
|
|||||||
fn title(&self, cx: &App) -> AnyElement;
|
fn title(&self, cx: &App) -> AnyElement;
|
||||||
fn closable(&self, cx: &App) -> bool;
|
fn closable(&self, cx: &App) -> bool;
|
||||||
fn zoomable(&self, cx: &App) -> bool;
|
fn zoomable(&self, cx: &App) -> bool;
|
||||||
|
fn visible(&self, cx: &App) -> bool;
|
||||||
|
fn set_active(&self, active: bool, cx: &mut App);
|
||||||
|
fn set_zoomed(&self, zoomed: bool, cx: &mut App);
|
||||||
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu;
|
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu;
|
||||||
fn toolbar_buttons(&self, window: &Window, cx: &App) -> Vec<Button>;
|
fn toolbar_buttons(&self, window: &Window, cx: &App) -> Vec<Button>;
|
||||||
fn view(&self) -> AnyView;
|
fn view(&self) -> AnyView;
|
||||||
@@ -95,6 +119,21 @@ impl<T: Panel> PanelView for Entity<T> {
|
|||||||
self.read(cx).zoomable(cx)
|
self.read(cx).zoomable(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visible(&self, cx: &App) -> bool {
|
||||||
|
self.read(cx).visible(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_active(&self, active: bool, cx: &mut App) {
|
||||||
|
self.update(cx, |this, cx| {
|
||||||
|
this.set_active(active, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn set_zoomed(&self, zoomed: bool, cx: &mut App) {
|
||||||
|
self.update(cx, |this, cx| {
|
||||||
|
this.set_zoomed(zoomed, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu {
|
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu {
|
||||||
self.read(cx).popup_menu(menu, cx)
|
self.read(cx).popup_menu(menu, cx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ impl StackPanel {
|
|||||||
fn new_resizable_panel(panel: Arc<dyn PanelView>, size: Option<Pixels>) -> ResizablePanel {
|
fn new_resizable_panel(panel: Arc<dyn PanelView>, size: Option<Pixels>) -> ResizablePanel {
|
||||||
resizable_panel()
|
resizable_panel()
|
||||||
.content_view(panel.view())
|
.content_view(panel.view())
|
||||||
|
.content_visible(move |cx| panel.visible(cx))
|
||||||
.when_some(size, |this, size| this.size(size))
|
.when_some(size, |this, size| this.size(size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,22 +9,24 @@ use crate::{
|
|||||||
popup_menu::{PopupMenu, PopupMenuExt},
|
popup_menu::{PopupMenu, PopupMenuExt},
|
||||||
tab::{tab_bar::TabBar, Tab},
|
tab::{tab_bar::TabBar, Tab},
|
||||||
theme::{scale::ColorScaleStep, ActiveTheme},
|
theme::{scale::ColorScaleStep, ActiveTheme},
|
||||||
v_flex, AxisExt, IconName, Placement, Selectable, Sizable,
|
v_flex, AxisExt, IconName, Placement, Selectable, Sizable, StyledExt,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, img, prelude::FluentBuilder, px, rems, App, AppContext, Context, Corner, DefiniteLength,
|
div, img, prelude::FluentBuilder, px, rems, App, AppContext, Context, Corner, DefiniteLength,
|
||||||
DismissEvent, DragMoveEvent, Empty, Entity, EventEmitter, FocusHandle, Focusable,
|
DismissEvent, DragMoveEvent, Empty, Entity, EventEmitter, FocusHandle, Focusable,
|
||||||
InteractiveElement as _, IntoElement, ObjectFit, ParentElement, Pixels, Render, ScrollHandle,
|
InteractiveElement as _, IntoElement, ObjectFit, ParentElement, Pixels, Render, ScrollHandle,
|
||||||
SharedString, StatefulInteractiveElement, Styled, StyledImage, WeakEntity, Window,
|
SharedString, StatefulInteractiveElement, StyleRefinement, Styled, StyledImage, WeakEntity,
|
||||||
|
Window,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone)]
|
||||||
struct TabState {
|
struct TabState {
|
||||||
closable: bool,
|
closable: bool,
|
||||||
zoomable: bool,
|
zoomable: bool,
|
||||||
draggable: bool,
|
draggable: bool,
|
||||||
droppable: bool,
|
droppable: bool,
|
||||||
|
active_panel: Option<Arc<dyn PanelView>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -84,7 +86,7 @@ impl Panel for TabPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, cx: &App) -> gpui::AnyElement {
|
fn title(&self, cx: &App) -> gpui::AnyElement {
|
||||||
self.active_panel()
|
self.active_panel(cx)
|
||||||
.map(|panel| panel.title(cx))
|
.map(|panel| panel.title(cx))
|
||||||
.unwrap_or("Empty Tab".into_any_element())
|
.unwrap_or("Empty Tab".into_any_element())
|
||||||
}
|
}
|
||||||
@@ -94,19 +96,23 @@ impl Panel for TabPanel {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.active_panel()
|
self.active_panel(cx)
|
||||||
.map(|panel| panel.closable(cx))
|
.map(|panel| panel.closable(cx))
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zoomable(&self, cx: &App) -> bool {
|
fn zoomable(&self, cx: &App) -> bool {
|
||||||
self.active_panel()
|
self.active_panel(cx)
|
||||||
.map(|panel| panel.zoomable(cx))
|
.map(|panel| panel.zoomable(cx))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visible(&self, cx: &App) -> bool {
|
||||||
|
self.visible_panels(cx).next().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu {
|
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu {
|
||||||
if let Some(panel) = self.active_panel() {
|
if let Some(panel) = self.active_panel(cx) {
|
||||||
panel.popup_menu(menu, cx)
|
panel.popup_menu(menu, cx)
|
||||||
} else {
|
} else {
|
||||||
menu
|
menu
|
||||||
@@ -114,7 +120,7 @@ impl Panel for TabPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn toolbar_buttons(&self, window: &Window, cx: &App) -> Vec<Button> {
|
fn toolbar_buttons(&self, window: &Window, cx: &App) -> Vec<Button> {
|
||||||
if let Some(panel) = self.active_panel() {
|
if let Some(panel) = self.active_panel(cx) {
|
||||||
panel.toolbar_buttons(window, cx)
|
panel.toolbar_buttons(window, cx)
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
@@ -147,15 +153,48 @@ impl TabPanel {
|
|||||||
self.stack_panel = Some(view);
|
self.stack_panel = Some(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return current active_panel View
|
/// Return current active_panel view
|
||||||
pub fn active_panel(&self) -> Option<Arc<dyn PanelView>> {
|
pub fn active_panel(&self, cx: &App) -> Option<Arc<dyn PanelView>> {
|
||||||
self.panels.get(self.active_ix).cloned()
|
let panel = self.panels.get(self.active_ix);
|
||||||
|
|
||||||
|
if let Some(panel) = panel {
|
||||||
|
if panel.visible(cx) {
|
||||||
|
Some(panel.clone())
|
||||||
|
} else {
|
||||||
|
// Return the first visible panel
|
||||||
|
self.visible_panels(cx).next()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_active_ix(&mut self, ix: usize, window: &mut Window, cx: &mut Context<Self>) {
|
fn set_active_ix(&mut self, ix: usize, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
|
if ix == self.active_ix {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_active_ix = self.active_ix;
|
||||||
|
|
||||||
self.active_ix = ix;
|
self.active_ix = ix;
|
||||||
self.tab_bar_scroll_handle.scroll_to_item(ix);
|
self.tab_bar_scroll_handle.scroll_to_item(ix);
|
||||||
self.focus_active_panel(window, cx);
|
self.focus_active_panel(window, cx);
|
||||||
|
|
||||||
|
// Sync the active state to all panels
|
||||||
|
cx.spawn(|view, cx| async move {
|
||||||
|
_ = cx.update(|cx| {
|
||||||
|
_ = view.update(cx, |view, cx| {
|
||||||
|
if let Some(last_active) = view.panels.get(last_active_ix) {
|
||||||
|
last_active.set_active(false, cx);
|
||||||
|
}
|
||||||
|
if let Some(active) = view.panels.get(view.active_ix) {
|
||||||
|
active.set_active(true, cx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
|
||||||
cx.emit(PanelEvent::LayoutChanged);
|
cx.emit(PanelEvent::LayoutChanged);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
@@ -332,6 +371,17 @@ impl TabPanel {
|
|||||||
self.panels.len() <= 1
|
self.panels.len() <= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return all visible panels
|
||||||
|
fn visible_panels<'a>(&'a self, cx: &'a App) -> impl Iterator<Item = Arc<dyn PanelView>> + 'a {
|
||||||
|
self.panels.iter().filter_map(|panel| {
|
||||||
|
if panel.visible(cx) {
|
||||||
|
Some(panel.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if the tab panel is draggable.
|
/// Return true if the tab panel is draggable.
|
||||||
///
|
///
|
||||||
/// E.g. if the parent and self only have one panel, it is not draggable.
|
/// E.g. if the parent and self only have one panel, it is not draggable.
|
||||||
@@ -348,7 +398,7 @@ impl TabPanel {
|
|||||||
|
|
||||||
fn render_toolbar(
|
fn render_toolbar(
|
||||||
&self,
|
&self,
|
||||||
state: TabState,
|
state: &TabState,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
@@ -382,15 +432,20 @@ impl TabPanel {
|
|||||||
.icon(IconName::Ellipsis)
|
.icon(IconName::Ellipsis)
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.ghost()
|
.ghost()
|
||||||
.popup_menu(move |this, _window, cx| {
|
.popup_menu({
|
||||||
|
let zoomable = state.zoomable;
|
||||||
|
let closable = state.closable;
|
||||||
|
|
||||||
|
move |this, _window, cx| {
|
||||||
build_popup_menu(this, cx)
|
build_popup_menu(this, cx)
|
||||||
.when(state.zoomable, |this| {
|
.when(zoomable, |this| {
|
||||||
let name = if is_zoomed { "Zoom Out" } else { "Zoom In" };
|
let name = if is_zoomed { "Zoom Out" } else { "Zoom In" };
|
||||||
this.separator().menu(name, Box::new(ToggleZoom))
|
this.separator().menu(name, Box::new(ToggleZoom))
|
||||||
})
|
})
|
||||||
.when(state.closable, |this| {
|
.when(closable, |this| {
|
||||||
this.separator().menu("Close", Box::new(ClosePanel))
|
this.separator().menu("Close", Box::new(ClosePanel))
|
||||||
})
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.anchor(Corner::TopRight),
|
.anchor(Corner::TopRight),
|
||||||
)
|
)
|
||||||
@@ -481,7 +536,7 @@ impl TabPanel {
|
|||||||
|
|
||||||
fn render_title_bar(
|
fn render_title_bar(
|
||||||
&self,
|
&self,
|
||||||
state: TabState,
|
state: &TabState,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
@@ -499,6 +554,10 @@ impl TabPanel {
|
|||||||
if self.panels.len() == 1 && panel_style == PanelStyle::Default {
|
if self.panels.len() == 1 && panel_style == PanelStyle::Default {
|
||||||
let panel = self.panels.first().unwrap();
|
let panel = self.panels.first().unwrap();
|
||||||
|
|
||||||
|
if !panel.visible(cx) {
|
||||||
|
return div().into_any_element();
|
||||||
|
}
|
||||||
|
|
||||||
return h_flex()
|
return h_flex()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.items_center()
|
.items_center()
|
||||||
@@ -601,15 +660,20 @@ impl TabPanel {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.children(self.panels.iter().enumerate().map(|(ix, panel)| {
|
.children(self.panels.iter().enumerate().filter_map(|(ix, panel)| {
|
||||||
let mut active = ix == self.active_ix;
|
let mut active = state.active_panel.as_ref() == Some(panel);
|
||||||
let disabled = self.is_collapsed;
|
let disabled = self.is_collapsed;
|
||||||
|
|
||||||
|
if !panel.visible(cx) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// Always not show active tab style, if the panel is collapsed
|
// Always not show active tab style, if the panel is collapsed
|
||||||
if self.is_collapsed {
|
if self.is_collapsed {
|
||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(
|
||||||
Tab::new(("tab", ix), panel.title(cx), panel.panel_facepile(cx))
|
Tab::new(("tab", ix), panel.title(cx), panel.panel_facepile(cx))
|
||||||
.py_2()
|
.py_2()
|
||||||
.selected(active)
|
.selected(active)
|
||||||
@@ -632,7 +696,9 @@ impl TabPanel {
|
|||||||
this.rounded_l_none()
|
this.rounded_l_none()
|
||||||
.border_l_2()
|
.border_l_2()
|
||||||
.border_r_0()
|
.border_r_0()
|
||||||
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
|
.border_color(
|
||||||
|
cx.theme().base.step(cx, ColorScaleStep::FIVE),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.on_drop(cx.listener(
|
.on_drop(cx.listener(
|
||||||
move |this, drag: &DragPanel, window, cx| {
|
move |this, drag: &DragPanel, window, cx| {
|
||||||
@@ -641,7 +707,8 @@ impl TabPanel {
|
|||||||
},
|
},
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
})
|
}),
|
||||||
|
)
|
||||||
}))
|
}))
|
||||||
.child(
|
.child(
|
||||||
// empty space to allow move to last tab right
|
// empty space to allow move to last tab right
|
||||||
@@ -686,7 +753,7 @@ impl TabPanel {
|
|||||||
|
|
||||||
fn render_active_panel(
|
fn render_active_panel(
|
||||||
&self,
|
&self,
|
||||||
state: TabState,
|
state: &TabState,
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
@@ -694,8 +761,10 @@ impl TabPanel {
|
|||||||
return Empty {}.into_any_element();
|
return Empty {}.into_any_element();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.active_panel()
|
let Some(active_panel) = state.active_panel.as_ref() else {
|
||||||
.map(|panel| {
|
return Empty {}.into_any_element();
|
||||||
|
};
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.id("tab-content")
|
.id("tab-content")
|
||||||
.group("")
|
.group("")
|
||||||
@@ -710,7 +779,11 @@ impl TabPanel {
|
|||||||
.when(cx.theme().appearance.is_dark(), |this| this.shadow_lg())
|
.when(cx.theme().appearance.is_dark(), |this| this.shadow_lg())
|
||||||
.bg(cx.theme().background)
|
.bg(cx.theme().background)
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.child(panel.view()),
|
.child(
|
||||||
|
active_panel
|
||||||
|
.view()
|
||||||
|
.cached(StyleRefinement::default().v_flex().size_full()),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.when(state.droppable, |this| {
|
.when(state.droppable, |this| {
|
||||||
this.on_drag_move(cx.listener(Self::on_panel_drag_move))
|
this.on_drag_move(cx.listener(Self::on_panel_drag_move))
|
||||||
@@ -723,28 +796,19 @@ impl TabPanel {
|
|||||||
div()
|
div()
|
||||||
.rounded_lg()
|
.rounded_lg()
|
||||||
.border_1()
|
.border_1()
|
||||||
.border_color(
|
.border_color(cx.theme().accent.step(cx, ColorScaleStep::FOUR))
|
||||||
cx.theme().accent.step(cx, ColorScaleStep::FOUR),
|
.bg(cx.theme().accent.step_alpha(cx, ColorScaleStep::THREE))
|
||||||
)
|
|
||||||
.bg(cx
|
|
||||||
.theme()
|
|
||||||
.accent
|
|
||||||
.step_alpha(cx, ColorScaleStep::THREE))
|
|
||||||
.size_full(),
|
.size_full(),
|
||||||
)
|
)
|
||||||
.map(|this| match self.will_split_placement {
|
.map(|this| match self.will_split_placement {
|
||||||
Some(placement) => {
|
Some(placement) => {
|
||||||
let size = DefiniteLength::Fraction(0.35);
|
let size = DefiniteLength::Fraction(0.35);
|
||||||
match placement {
|
match placement {
|
||||||
Placement::Left => {
|
Placement::Left => this.left_0().top_0().bottom_0().w(size),
|
||||||
this.left_0().top_0().bottom_0().w(size)
|
|
||||||
}
|
|
||||||
Placement::Right => {
|
Placement::Right => {
|
||||||
this.right_0().top_0().bottom_0().w(size)
|
this.right_0().top_0().bottom_0().w(size)
|
||||||
}
|
}
|
||||||
Placement::Top => {
|
Placement::Top => this.top_0().left_0().right_0().h(size),
|
||||||
this.top_0().left_0().right_0().h(size)
|
|
||||||
}
|
|
||||||
Placement::Bottom => {
|
Placement::Bottom => {
|
||||||
this.bottom_0().left_0().right_0().h(size)
|
this.bottom_0().left_0().right_0().h(size)
|
||||||
}
|
}
|
||||||
@@ -759,8 +823,6 @@ impl TabPanel {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
})
|
|
||||||
.unwrap_or(Empty {}.into_any_element())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the split direction based on the current mouse position
|
/// Calculate the split direction based on the current mouse position
|
||||||
@@ -958,7 +1020,7 @@ impl TabPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn focus_active_panel(&self, window: &mut Window, cx: &mut Context<Self>) {
|
fn focus_active_panel(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if let Some(active_panel) = self.active_panel() {
|
if let Some(active_panel) = self.active_panel(cx) {
|
||||||
active_panel.focus_handle(cx).focus(window);
|
active_panel.focus_handle(cx).focus(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -980,6 +1042,18 @@ impl TabPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.is_zoomed = !self.is_zoomed;
|
self.is_zoomed = !self.is_zoomed;
|
||||||
|
|
||||||
|
cx.spawn(|view, cx| {
|
||||||
|
let is_zoomed = self.is_zoomed;
|
||||||
|
async move {
|
||||||
|
_ = cx.update(|cx| {
|
||||||
|
_ = view.update(cx, |view, cx| {
|
||||||
|
view.set_zoomed(is_zoomed, cx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_action_close_panel(
|
fn on_action_close_panel(
|
||||||
@@ -988,7 +1062,7 @@ impl TabPanel {
|
|||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(panel) = self.active_panel() {
|
if let Some(panel) = self.active_panel(cx) {
|
||||||
self.remove_panel(panel, window, cx);
|
self.remove_panel(panel, window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -996,7 +1070,7 @@ impl TabPanel {
|
|||||||
|
|
||||||
impl Focusable for TabPanel {
|
impl Focusable for TabPanel {
|
||||||
fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
|
fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
|
||||||
if let Some(active_panel) = self.active_panel() {
|
if let Some(active_panel) = self.active_panel(cx) {
|
||||||
active_panel.focus_handle(cx)
|
active_panel.focus_handle(cx)
|
||||||
} else {
|
} else {
|
||||||
self.focus_handle.clone()
|
self.focus_handle.clone()
|
||||||
@@ -1011,12 +1085,13 @@ impl EventEmitter<PanelEvent> for TabPanel {}
|
|||||||
impl Render for TabPanel {
|
impl Render for TabPanel {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl gpui::IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl gpui::IntoElement {
|
||||||
let focus_handle = self.focus_handle(cx);
|
let focus_handle = self.focus_handle(cx);
|
||||||
|
let active_panel = self.active_panel(cx);
|
||||||
let mut state = TabState {
|
let mut state = TabState {
|
||||||
closable: self.closable(cx),
|
closable: self.closable(cx),
|
||||||
draggable: self.draggable(cx),
|
draggable: self.draggable(cx),
|
||||||
droppable: self.droppable(cx),
|
droppable: self.droppable(cx),
|
||||||
zoomable: self.zoomable(cx),
|
zoomable: self.zoomable(cx),
|
||||||
|
active_panel,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !state.draggable {
|
if !state.draggable {
|
||||||
@@ -1030,7 +1105,7 @@ impl Render for TabPanel {
|
|||||||
.on_action(cx.listener(Self::on_action_close_panel))
|
.on_action(cx.listener(Self::on_action_close_panel))
|
||||||
.size_full()
|
.size_full()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.child(self.render_title_bar(state, window, cx))
|
.child(self.render_title_bar(&state, window, cx))
|
||||||
.child(self.render_active_panel(state, window, cx))
|
.child(self.render_active_panel(&state, window, cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1524,6 +1524,15 @@ impl EntityInputHandler for TextInput {
|
|||||||
bounds.origin + end_origin.unwrap_or_default(),
|
bounds.origin + end_origin.unwrap_or_default(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn character_index_for_point(
|
||||||
|
&mut self,
|
||||||
|
_point: gpui::Point<Pixels>,
|
||||||
|
_window: &mut Window,
|
||||||
|
_cx: &mut Context<Self>,
|
||||||
|
) -> Option<usize> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Focusable for TextInput {
|
impl Focusable for TextInput {
|
||||||
|
|||||||
@@ -304,6 +304,7 @@ impl Render for ResizablePanelGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ContentBuilder = Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyElement>>;
|
type ContentBuilder = Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyElement>>;
|
||||||
|
type ContentVisible = Rc<Box<dyn Fn(&App) -> bool>>;
|
||||||
|
|
||||||
pub struct ResizablePanel {
|
pub struct ResizablePanel {
|
||||||
group: Option<WeakEntity<ResizablePanelGroup>>,
|
group: Option<WeakEntity<ResizablePanelGroup>>,
|
||||||
@@ -316,6 +317,7 @@ pub struct ResizablePanel {
|
|||||||
axis: Axis,
|
axis: Axis,
|
||||||
content_builder: ContentBuilder,
|
content_builder: ContentBuilder,
|
||||||
content_view: Option<AnyView>,
|
content_view: Option<AnyView>,
|
||||||
|
content_visible: ContentVisible,
|
||||||
/// The bounds of the resizable panel, when render the bounds will be updated.
|
/// The bounds of the resizable panel, when render the bounds will be updated.
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
resize_handle: Option<AnyElement>,
|
resize_handle: Option<AnyElement>,
|
||||||
@@ -331,6 +333,7 @@ impl ResizablePanel {
|
|||||||
axis: Axis::Horizontal,
|
axis: Axis::Horizontal,
|
||||||
content_builder: None,
|
content_builder: None,
|
||||||
content_view: None,
|
content_view: None,
|
||||||
|
content_visible: Rc::new(Box::new(|_| true)),
|
||||||
bounds: Bounds::default(),
|
bounds: Bounds::default(),
|
||||||
resize_handle: None,
|
resize_handle: None,
|
||||||
}
|
}
|
||||||
@@ -344,6 +347,14 @@ impl ResizablePanel {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn content_visible<F>(mut self, content_visible: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(&App) -> bool + 'static,
|
||||||
|
{
|
||||||
|
self.content_visible = Rc::new(Box::new(content_visible));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn content_view(mut self, content: AnyView) -> Self {
|
pub fn content_view(mut self, content: AnyView) -> Self {
|
||||||
self.content_view = Some(content);
|
self.content_view = Some(content);
|
||||||
self
|
self
|
||||||
@@ -364,16 +375,14 @@ impl ResizablePanel {
|
|||||||
) {
|
) {
|
||||||
let new_size = bounds.size.along(self.axis);
|
let new_size = bounds.size.along(self.axis);
|
||||||
self.bounds = bounds;
|
self.bounds = bounds;
|
||||||
|
self.size_ratio = None;
|
||||||
self.size = Some(new_size);
|
self.size = Some(new_size);
|
||||||
|
|
||||||
let panel_view = cx.entity().clone();
|
let entity_id = cx.entity_id();
|
||||||
|
|
||||||
if let Some(group) = self.group.as_ref() {
|
if let Some(group) = self.group.as_ref() {
|
||||||
_ = group.update(cx, |view, _| {
|
_ = group.update(cx, |view, _| {
|
||||||
if let Some(ix) = view
|
if let Some(ix) = view.panels.iter().position(|v| v.entity_id() == entity_id) {
|
||||||
.panels
|
|
||||||
.iter()
|
|
||||||
.position(|v| v.entity_id() == panel_view.entity_id())
|
|
||||||
{
|
|
||||||
view.sizes[ix] = new_size;
|
view.sizes[ix] = new_size;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -386,6 +395,14 @@ impl FluentBuilder for ResizablePanel {}
|
|||||||
|
|
||||||
impl Render for ResizablePanel {
|
impl Render for ResizablePanel {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
|
if !(self.content_visible)(cx) {
|
||||||
|
// To keep size as initial size, to make sure the size will not be changed.
|
||||||
|
self.initial_size = self.size;
|
||||||
|
self.size = None;
|
||||||
|
|
||||||
|
return div();
|
||||||
|
}
|
||||||
|
|
||||||
let view = cx.entity().clone();
|
let view = cx.entity().clone();
|
||||||
let total_size = self
|
let total_size = self
|
||||||
.group
|
.group
|
||||||
|
|||||||
@@ -589,6 +589,11 @@ impl Element for Scrollbar {
|
|||||||
let is_visible = self.state.get().is_scrollbar_visible();
|
let is_visible = self.state.get().is_scrollbar_visible();
|
||||||
let is_hover_to_show = cx.theme().scrollbar_show.is_hover();
|
let is_hover_to_show = cx.theme().scrollbar_show.is_hover();
|
||||||
|
|
||||||
|
window.with_content_mask(
|
||||||
|
Some(ContentMask {
|
||||||
|
bounds: hitbox_bounds,
|
||||||
|
}),
|
||||||
|
|window| {
|
||||||
for state in prepaint.states.iter() {
|
for state in prepaint.states.iter() {
|
||||||
let axis = state.axis;
|
let axis = state.axis;
|
||||||
let radius = state.radius;
|
let radius = state.radius;
|
||||||
@@ -627,7 +632,9 @@ impl Element for Scrollbar {
|
|||||||
border_color: state.border,
|
border_color: state.border,
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.paint_quad(fill(state.thumb_fill_bounds, state.thumb_bg).corner_radii(radius));
|
cx.paint_quad(
|
||||||
|
fill(state.thumb_fill_bounds, state.thumb_bg).corner_radii(radius),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.on_mouse_event({
|
window.on_mouse_event({
|
||||||
@@ -640,11 +647,10 @@ impl Element for Scrollbar {
|
|||||||
&& hitbox_bounds.contains(&event.position)
|
&& hitbox_bounds.contains(&event.position)
|
||||||
&& scroll_handle.offset() != state.get().last_scroll_offset
|
&& scroll_handle.offset() != state.get().last_scroll_offset
|
||||||
{
|
{
|
||||||
state.set(
|
state.set(state.get().with_last_scroll(
|
||||||
state
|
scroll_handle.offset(),
|
||||||
.get()
|
Some(Instant::now()),
|
||||||
.with_last_scroll(scroll_handle.offset(), Some(Instant::now())),
|
));
|
||||||
);
|
|
||||||
cx.notify(view_id);
|
cx.notify(view_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -782,5 +788,7 @@ impl Element for Scrollbar {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user