dock: Add version to DockArea to allow us check the persisted state is need to update. (#323)
This commit is contained in:
parent
45d4b445ec
commit
0220cf8cc6
8 changed files with 108 additions and 43 deletions
|
|
@ -21,6 +21,11 @@ use workspace::TitleBar;
|
||||||
|
|
||||||
use crate::app_state::AppState;
|
use crate::app_state::AppState;
|
||||||
|
|
||||||
|
const MAIN_DOCK_AREA: DockAreaTab = DockAreaTab {
|
||||||
|
id: "main-dock",
|
||||||
|
version: 3,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||||
struct SelectLocale(SharedString);
|
struct SelectLocale(SharedString);
|
||||||
|
|
||||||
|
|
@ -43,6 +48,11 @@ pub struct StoryWorkspace {
|
||||||
_save_layout_task: Option<Task<()>>,
|
_save_layout_task: Option<Task<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DockAreaTab {
|
||||||
|
id: &'static str,
|
||||||
|
version: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl StoryWorkspace {
|
impl StoryWorkspace {
|
||||||
pub fn new(_app_state: Arc<AppState>, cx: &mut ViewContext<Self>) -> Self {
|
pub fn new(_app_state: Arc<AppState>, cx: &mut ViewContext<Self>) -> Self {
|
||||||
cx.observe_window_appearance(|_, cx| {
|
cx.observe_window_appearance(|_, cx| {
|
||||||
|
|
@ -50,7 +60,8 @@ impl StoryWorkspace {
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
let dock_area = cx.new_view(|cx| DockArea::new("main-dock", cx));
|
let dock_area =
|
||||||
|
cx.new_view(|cx| DockArea::new(MAIN_DOCK_AREA.id, Some(MAIN_DOCK_AREA.version), cx));
|
||||||
let weak_dock_area = dock_area.downgrade();
|
let weak_dock_area = dock_area.downgrade();
|
||||||
|
|
||||||
match Self::load_layout(dock_area.clone(), cx) {
|
match Self::load_layout(dock_area.clone(), cx) {
|
||||||
|
|
@ -59,25 +70,7 @@ impl StoryWorkspace {
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("load layout error: {:?}", err);
|
eprintln!("load layout error: {:?}", err);
|
||||||
let dock_item = Self::init_default_layout(&weak_dock_area, cx);
|
Self::reset_default_layout(weak_dock_area, cx);
|
||||||
|
|
||||||
let left_panels: Vec<Arc<dyn PanelView>> =
|
|
||||||
vec![Arc::new(StoryContainer::panel::<ListStory>(cx))];
|
|
||||||
|
|
||||||
let bottom_panels: Vec<Arc<dyn PanelView>> = vec![
|
|
||||||
Arc::new(StoryContainer::panel::<TooltipStory>(cx)),
|
|
||||||
Arc::new(StoryContainer::panel::<IconStory>(cx)),
|
|
||||||
];
|
|
||||||
|
|
||||||
let right_panels: Vec<Arc<dyn PanelView>> =
|
|
||||||
vec![Arc::new(StoryContainer::panel::<ImageStory>(cx))];
|
|
||||||
|
|
||||||
_ = dock_area.update(cx, |view, cx| {
|
|
||||||
view.set_root(dock_item, cx);
|
|
||||||
view.set_left_dock(left_panels, Some(px(350.)), cx);
|
|
||||||
view.set_bottom_dock(bottom_panels, Some(px(200.)), cx);
|
|
||||||
view.set_right_dock(right_panels, Some(px(320.)), cx);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -166,6 +159,23 @@ impl StoryWorkspace {
|
||||||
let json = std::fs::read_to_string(fname)?;
|
let json = std::fs::read_to_string(fname)?;
|
||||||
let state = serde_json::from_str::<DockAreaState>(&json)?;
|
let state = serde_json::from_str::<DockAreaState>(&json)?;
|
||||||
|
|
||||||
|
// Check if the saved layout version is different from the current version
|
||||||
|
// Notify the user and ask if they want to reset the layout to default.
|
||||||
|
if state.version != Some(MAIN_DOCK_AREA.version) {
|
||||||
|
let answer = cx.prompt(PromptLevel::Info, "The default main layout has been updated.\nDo you want to reset the layout to default?", None,
|
||||||
|
&["Yes", "No"]);
|
||||||
|
|
||||||
|
let weak_dock_area = dock_area.downgrade();
|
||||||
|
cx.spawn(|mut cx| async move {
|
||||||
|
if answer.await == Ok(0) {
|
||||||
|
_ = cx.update(|cx| {
|
||||||
|
Self::reset_default_layout(weak_dock_area, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
dock_area.update(cx, |dock_area, cx| {
|
dock_area.update(cx, |dock_area, cx| {
|
||||||
dock_area.load(state, cx).context("load layout")?;
|
dock_area.load(state, cx).context("load layout")?;
|
||||||
|
|
||||||
|
|
@ -173,6 +183,30 @@ impl StoryWorkspace {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset_default_layout(dock_area: WeakView<DockArea>, cx: &mut WindowContext) {
|
||||||
|
let dock_item = Self::init_default_layout(&dock_area, cx);
|
||||||
|
let left_panels: Vec<Arc<dyn PanelView>> =
|
||||||
|
vec![Arc::new(StoryContainer::panel::<ListStory>(cx))];
|
||||||
|
|
||||||
|
let bottom_panels: Vec<Arc<dyn PanelView>> = vec![
|
||||||
|
Arc::new(StoryContainer::panel::<TooltipStory>(cx)),
|
||||||
|
Arc::new(StoryContainer::panel::<IconStory>(cx)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let right_panels: Vec<Arc<dyn PanelView>> =
|
||||||
|
vec![Arc::new(StoryContainer::panel::<ImageStory>(cx))];
|
||||||
|
|
||||||
|
_ = dock_area.update(cx, |view, cx| {
|
||||||
|
view.set_version(MAIN_DOCK_AREA.version, cx);
|
||||||
|
view.set_root(dock_item, cx);
|
||||||
|
view.set_left_dock(left_panels, Some(px(350.)), cx);
|
||||||
|
view.set_bottom_dock(bottom_panels, Some(px(200.)), cx);
|
||||||
|
view.set_right_dock(right_panels, Some(px(320.)), cx);
|
||||||
|
|
||||||
|
Self::save_state(&view.dump(cx)).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn init_default_layout(dock_area: &WeakView<DockArea>, cx: &mut WindowContext) -> DockItem {
|
fn init_default_layout(dock_area: &WeakView<DockArea>, cx: &mut WindowContext) -> DockItem {
|
||||||
DockItem::split_with_sizes(
|
DockItem::split_with_sizes(
|
||||||
Axis::Vertical,
|
Axis::Vertical,
|
||||||
|
|
@ -180,8 +214,8 @@ impl StoryWorkspace {
|
||||||
vec![
|
vec![
|
||||||
Arc::new(StoryContainer::panel::<ButtonStory>(cx)),
|
Arc::new(StoryContainer::panel::<ButtonStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<InputStory>(cx)),
|
Arc::new(StoryContainer::panel::<InputStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<TextStory>(cx)),
|
|
||||||
Arc::new(StoryContainer::panel::<DropdownStory>(cx)),
|
Arc::new(StoryContainer::panel::<DropdownStory>(cx)),
|
||||||
|
Arc::new(StoryContainer::panel::<TextStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<ModalStory>(cx)),
|
Arc::new(StoryContainer::panel::<ModalStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<PopupStory>(cx)),
|
Arc::new(StoryContainer::panel::<PopupStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<SwitchStory>(cx)),
|
Arc::new(StoryContainer::panel::<SwitchStory>(cx)),
|
||||||
|
|
@ -191,10 +225,10 @@ impl StoryWorkspace {
|
||||||
Arc::new(StoryContainer::panel::<IconStory>(cx)),
|
Arc::new(StoryContainer::panel::<IconStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<TooltipStory>(cx)),
|
Arc::new(StoryContainer::panel::<TooltipStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<ProgressStory>(cx)),
|
Arc::new(StoryContainer::panel::<ProgressStory>(cx)),
|
||||||
|
Arc::new(StoryContainer::panel::<WebViewStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<CalendarStory>(cx)),
|
Arc::new(StoryContainer::panel::<CalendarStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<ResizableStory>(cx)),
|
Arc::new(StoryContainer::panel::<ResizableStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<ScrollableStory>(cx)),
|
Arc::new(StoryContainer::panel::<ScrollableStory>(cx)),
|
||||||
Arc::new(StoryContainer::panel::<WebViewStory>(cx)),
|
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
&dock_area,
|
&dock_area,
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,16 @@ use ui::{
|
||||||
v_flex, ContextModal,
|
v_flex, ContextModal,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PANEL_NAME: &str = "StoryContainer";
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
input_story::init(cx);
|
input_story::init(cx);
|
||||||
dropdown_story::init(cx);
|
dropdown_story::init(cx);
|
||||||
popup_story::init(cx);
|
popup_story::init(cx);
|
||||||
|
|
||||||
register_panel(cx, "StoryContainer", |_, info, cx| {
|
register_panel(cx, PANEL_NAME, |_, _, info, cx| {
|
||||||
let story_state = match info {
|
let story_state = match info {
|
||||||
DockItemInfo::Panel(value) => StoryState::from_value(value),
|
DockItemInfo::Panel(value) => StoryState::from_value(value.clone()),
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!("Invalid DockItemInfo: {:?}", info)
|
unreachable!("Invalid DockItemInfo: {:?}", info)
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +294,7 @@ impl Panel for StoryContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump(&self, _cx: &AppContext) -> DockItemState {
|
fn dump(&self, _cx: &AppContext) -> DockItemState {
|
||||||
let mut state = DockItemState::new(self.panel_name());
|
let mut state = DockItemState::new(self);
|
||||||
let story_state = StoryState {
|
let story_state = StoryState {
|
||||||
story_klass: self.story_klass.clone().unwrap(),
|
story_klass: self.story_klass.clone().unwrap(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ impl Panel for InvalidPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump(&self, _cx: &AppContext) -> super::DockItemState {
|
fn dump(&self, _cx: &AppContext) -> super::DockItemState {
|
||||||
let mut state = DockItemState::new(&self.name);
|
let mut state = DockItemState::new(self);
|
||||||
state.info = self.info.clone();
|
state.info = self.info.clone();
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ pub enum DockEvent {
|
||||||
/// The main area of the dock.
|
/// The main area of the dock.
|
||||||
pub struct DockArea {
|
pub struct DockArea {
|
||||||
id: SharedString,
|
id: SharedString,
|
||||||
|
/// The version is used to special the default layout, this is like the `panel_version` in `trait Panel`.
|
||||||
|
version: Option<usize>,
|
||||||
pub(crate) bounds: Bounds<Pixels>,
|
pub(crate) bounds: Bounds<Pixels>,
|
||||||
|
|
||||||
/// The center view of the dockarea.
|
/// The center view of the dockarea.
|
||||||
|
|
@ -181,7 +183,11 @@ impl DockItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DockArea {
|
impl DockArea {
|
||||||
pub fn new(id: impl Into<SharedString>, cx: &mut ViewContext<Self>) -> Self {
|
pub fn new(
|
||||||
|
id: impl Into<SharedString>,
|
||||||
|
version: Option<usize>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Self {
|
||||||
let stack_panel = cx.new_view(|cx| StackPanel::new(Axis::Horizontal, cx));
|
let stack_panel = cx.new_view(|cx| StackPanel::new(Axis::Horizontal, cx));
|
||||||
let dock_item = DockItem::Split {
|
let dock_item = DockItem::Split {
|
||||||
axis: Axis::Horizontal,
|
axis: Axis::Horizontal,
|
||||||
|
|
@ -192,6 +198,7 @@ impl DockArea {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
|
version,
|
||||||
bounds: Bounds::default(),
|
bounds: Bounds::default(),
|
||||||
items: dock_item,
|
items: dock_item,
|
||||||
zoom_view: None,
|
zoom_view: None,
|
||||||
|
|
@ -201,6 +208,12 @@ impl DockArea {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set version of the dock area.
|
||||||
|
pub fn set_version(&mut self, version: usize, cx: &mut ViewContext<Self>) {
|
||||||
|
self.version = Some(version);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
/// The the DockItem as the root of the dock area.
|
/// The the DockItem as the root of the dock area.
|
||||||
///
|
///
|
||||||
/// This is used to render at the Center of the DockArea.
|
/// This is used to render at the Center of the DockArea.
|
||||||
|
|
@ -299,6 +312,7 @@ impl DockArea {
|
||||||
///
|
///
|
||||||
/// See also [DockeArea::dump].
|
/// See also [DockeArea::dump].
|
||||||
pub fn load(&mut self, state: DockAreaState, cx: &mut ViewContext<Self>) -> Result<()> {
|
pub fn load(&mut self, state: DockAreaState, cx: &mut ViewContext<Self>) -> Result<()> {
|
||||||
|
self.version = state.version;
|
||||||
let weak_self = cx.view().downgrade();
|
let weak_self = cx.view().downgrade();
|
||||||
|
|
||||||
if let Some(left_dock) = state.left_dock {
|
if let Some(left_dock) = state.left_dock {
|
||||||
|
|
@ -348,6 +362,7 @@ impl DockArea {
|
||||||
.map(|dock| DockState::new(dock.clone(), cx));
|
.map(|dock| DockState::new(dock.clone(), cx));
|
||||||
|
|
||||||
DockAreaState {
|
DockAreaState {
|
||||||
|
version: self.version,
|
||||||
center,
|
center,
|
||||||
left_dock,
|
left_dock,
|
||||||
right_dock,
|
right_dock,
|
||||||
|
|
|
||||||
|
|
@ -60,26 +60,20 @@ pub trait Panel: EventEmitter<PanelEvent> + FocusableView {
|
||||||
|
|
||||||
/// Dump the panel, used to serialize the panel.
|
/// Dump the panel, used to serialize the panel.
|
||||||
fn dump(&self, _cx: &AppContext) -> DockItemState {
|
fn dump(&self, _cx: &AppContext) -> DockItemState {
|
||||||
DockItemState::new(self.panel_name())
|
DockItemState::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PanelView: 'static + Send + Sync {
|
pub trait PanelView: 'static + Send + Sync {
|
||||||
fn panel_name(&self, _cx: &WindowContext) -> &'static str;
|
fn panel_name(&self, _cx: &WindowContext) -> &'static str;
|
||||||
fn title(&self, _cx: &WindowContext) -> AnyElement;
|
fn title(&self, _cx: &WindowContext) -> AnyElement;
|
||||||
|
|
||||||
fn title_style(&self, _cx: &WindowContext) -> Option<TitleStyle>;
|
fn title_style(&self, _cx: &WindowContext) -> Option<TitleStyle>;
|
||||||
|
|
||||||
fn closeable(&self, cx: &WindowContext) -> bool;
|
fn closeable(&self, cx: &WindowContext) -> bool;
|
||||||
fn zoomable(&self, cx: &WindowContext) -> bool;
|
fn zoomable(&self, cx: &WindowContext) -> bool;
|
||||||
fn collapsible(&self, cx: &WindowContext) -> bool;
|
fn collapsible(&self, cx: &WindowContext) -> bool;
|
||||||
|
|
||||||
fn popup_menu(&self, menu: PopupMenu, cx: &WindowContext) -> PopupMenu;
|
fn popup_menu(&self, menu: PopupMenu, cx: &WindowContext) -> PopupMenu;
|
||||||
|
|
||||||
fn view(&self) -> AnyView;
|
fn view(&self) -> AnyView;
|
||||||
|
|
||||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
|
fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
|
||||||
|
|
||||||
fn dump(&self, cx: &AppContext) -> DockItemState;
|
fn dump(&self, cx: &AppContext) -> DockItemState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,6 +81,7 @@ impl<T: Panel> PanelView for View<T> {
|
||||||
fn panel_name(&self, cx: &WindowContext) -> &'static str {
|
fn panel_name(&self, cx: &WindowContext) -> &'static str {
|
||||||
self.read(cx).panel_name()
|
self.read(cx).panel_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, cx: &WindowContext) -> AnyElement {
|
fn title(&self, cx: &WindowContext) -> AnyElement {
|
||||||
self.read(cx).title(cx)
|
self.read(cx).title(cx)
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +140,14 @@ impl PartialEq for dyn PanelView {
|
||||||
pub struct PanelRegistry {
|
pub struct PanelRegistry {
|
||||||
pub(super) items: HashMap<
|
pub(super) items: HashMap<
|
||||||
String,
|
String,
|
||||||
Arc<dyn Fn(WeakView<DockArea>, DockItemInfo, &mut WindowContext) -> Box<dyn PanelView>>,
|
Arc<
|
||||||
|
dyn Fn(
|
||||||
|
WeakView<DockArea>,
|
||||||
|
&DockItemState,
|
||||||
|
&DockItemInfo,
|
||||||
|
&mut WindowContext,
|
||||||
|
) -> Box<dyn PanelView>,
|
||||||
|
>,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
impl PanelRegistry {
|
impl PanelRegistry {
|
||||||
|
|
@ -160,7 +162,13 @@ impl Global for PanelRegistry {}
|
||||||
/// Register the Panel init by panel_name to global registry.
|
/// Register the Panel init by panel_name to global registry.
|
||||||
pub fn register_panel<F>(cx: &mut AppContext, panel_name: &str, deserialize: F)
|
pub fn register_panel<F>(cx: &mut AppContext, panel_name: &str, deserialize: F)
|
||||||
where
|
where
|
||||||
F: Fn(WeakView<DockArea>, DockItemInfo, &mut WindowContext) -> Box<dyn PanelView> + 'static,
|
F: Fn(
|
||||||
|
WeakView<DockArea>,
|
||||||
|
&DockItemState,
|
||||||
|
&DockItemInfo,
|
||||||
|
&mut WindowContext,
|
||||||
|
) -> Box<dyn PanelView>
|
||||||
|
+ 'static,
|
||||||
{
|
{
|
||||||
if let None = cx.try_global::<PanelRegistry>() {
|
if let None = cx.try_global::<PanelRegistry>() {
|
||||||
cx.set_global(PanelRegistry::new());
|
cx.set_global(PanelRegistry::new());
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ impl Panel for StackPanel {
|
||||||
|
|
||||||
fn dump(&self, cx: &AppContext) -> DockItemState {
|
fn dump(&self, cx: &AppContext) -> DockItemState {
|
||||||
let sizes = self.panel_group.read(cx).sizes();
|
let sizes = self.panel_group.read(cx).sizes();
|
||||||
let mut state = DockItemState::new(self.panel_name());
|
let mut state = DockItemState::new(self);
|
||||||
for panel in &self.panels {
|
for panel in &self.panels {
|
||||||
state.add_child(panel.dump(cx));
|
state.add_child(panel.dump(cx));
|
||||||
state.info = DockItemInfo::stack(sizes.clone(), self.axis);
|
state.info = DockItemInfo::stack(sizes.clone(), self.axis);
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,18 @@ use itertools::Itertools as _;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
invalid_panel::InvalidPanel, Dock, DockArea, DockItem, DockPlacement, PanelRegistry, PanelView,
|
invalid_panel::InvalidPanel, Dock, DockArea, DockItem, DockPlacement, Panel, PanelRegistry,
|
||||||
TabPanel,
|
PanelView, TabPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Used to serialize and deserialize the DockArea
|
/// Used to serialize and deserialize the DockArea
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct DockAreaState {
|
pub struct DockAreaState {
|
||||||
|
/// The version is used to mark this persisted state is compatible with the current version
|
||||||
|
/// For example, some times we many totally changed the structure of the Panel,
|
||||||
|
/// then we can compare the version to decide whether we can use the state or ignore.
|
||||||
|
#[serde(default)]
|
||||||
|
pub version: Option<usize>,
|
||||||
pub center: DockItemState,
|
pub center: DockItemState,
|
||||||
pub left_dock: Option<DockState>,
|
pub left_dock: Option<DockState>,
|
||||||
pub right_dock: Option<DockState>,
|
pub right_dock: Option<DockState>,
|
||||||
|
|
@ -138,9 +143,9 @@ impl Default for DockItemState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DockItemState {
|
impl DockItemState {
|
||||||
pub fn new(panel_name: &str) -> Self {
|
pub fn new<P: Panel>(panel: &P) -> Self {
|
||||||
Self {
|
Self {
|
||||||
panel_name: panel_name.to_string(),
|
panel_name: panel.panel_name().to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +197,7 @@ impl DockItemState {
|
||||||
.get(&self.panel_name)
|
.get(&self.panel_name)
|
||||||
.cloned()
|
.cloned()
|
||||||
{
|
{
|
||||||
f(dock_area.clone(), info.clone(), cx)
|
f(dock_area.clone(), self, &info, cx)
|
||||||
} else {
|
} else {
|
||||||
// Show an invalid panel if the panel is not registered.
|
// Show an invalid panel if the panel is not registered.
|
||||||
Box::new(
|
Box::new(
|
||||||
|
|
@ -215,6 +220,7 @@ mod tests {
|
||||||
fn test_deserialize_item_state() {
|
fn test_deserialize_item_state() {
|
||||||
let json = include_str!("../../tests/fixtures/layout.json");
|
let json = include_str!("../../tests/fixtures/layout.json");
|
||||||
let state: DockAreaState = serde_json::from_str(json).unwrap();
|
let state: DockAreaState = serde_json::from_str(json).unwrap();
|
||||||
|
assert_eq!(state.version, None);
|
||||||
assert_eq!(state.center.panel_name, "StackPanel");
|
assert_eq!(state.center.panel_name, "StackPanel");
|
||||||
assert_eq!(state.center.children.len(), 2);
|
assert_eq!(state.center.children.len(), 2);
|
||||||
assert_eq!(state.center.children[0].panel_name, "TabPanel");
|
assert_eq!(state.center.children[0].panel_name, "TabPanel");
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ impl Panel for TabPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump(&self, cx: &AppContext) -> DockItemState {
|
fn dump(&self, cx: &AppContext) -> DockItemState {
|
||||||
let mut state = DockItemState::new(self.panel_name());
|
let mut state = DockItemState::new(self);
|
||||||
for panel in self.panels.iter() {
|
for panel in self.panels.iter() {
|
||||||
state.add_child(panel.dump(cx));
|
state.add_child(panel.dump(cx));
|
||||||
state.info = DockItemInfo::tabs(self.active_ix);
|
state.info = DockItemInfo::tabs(self.active_ix);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue