Re-activate the most recently-activated project search on cmd-shift-F
This commits adds the beginnings of an application state facility as a non-static place to store the most recently-activated search for each project. I also store workspace items by descending order of their entity id so that we always fetch the newest item of a given type when calling `Workspace::item_of_type`.
This commit is contained in:
parent
1ddae2adfd
commit
cb230ad574
4 changed files with 122 additions and 17 deletions
|
@ -85,6 +85,8 @@ pub trait UpgradeModelHandle {
|
||||||
handle: &WeakModelHandle<T>,
|
handle: &WeakModelHandle<T>,
|
||||||
) -> Option<ModelHandle<T>>;
|
) -> Option<ModelHandle<T>>;
|
||||||
|
|
||||||
|
fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool;
|
||||||
|
|
||||||
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle>;
|
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,6 +610,10 @@ impl UpgradeModelHandle for AsyncAppContext {
|
||||||
self.0.borrow().upgrade_model_handle(handle)
|
self.0.borrow().upgrade_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
|
||||||
|
self.0.borrow().model_handle_is_upgradable(handle)
|
||||||
|
}
|
||||||
|
|
||||||
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
||||||
self.0.borrow().upgrade_any_model_handle(handle)
|
self.0.borrow().upgrade_any_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
@ -763,6 +769,7 @@ impl MutableAppContext {
|
||||||
models: Default::default(),
|
models: Default::default(),
|
||||||
views: Default::default(),
|
views: Default::default(),
|
||||||
windows: Default::default(),
|
windows: Default::default(),
|
||||||
|
app_states: Default::default(),
|
||||||
element_states: Default::default(),
|
element_states: Default::default(),
|
||||||
ref_counts: Arc::new(Mutex::new(RefCounts::default())),
|
ref_counts: Arc::new(Mutex::new(RefCounts::default())),
|
||||||
background,
|
background,
|
||||||
|
@ -1306,6 +1313,27 @@ impl MutableAppContext {
|
||||||
Ok(pending)
|
Ok(pending)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_app_state<T: 'static>(&mut self, state: T) {
|
||||||
|
self.cx
|
||||||
|
.app_states
|
||||||
|
.insert(TypeId::of::<T>(), Box::new(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_app_state<T: 'static, F, U>(&mut self, update: F) -> U
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut T, &mut MutableAppContext) -> U,
|
||||||
|
{
|
||||||
|
let type_id = TypeId::of::<T>();
|
||||||
|
let mut state = self
|
||||||
|
.cx
|
||||||
|
.app_states
|
||||||
|
.remove(&type_id)
|
||||||
|
.expect("no app state has been added for this type");
|
||||||
|
let result = update(state.downcast_mut().unwrap(), self);
|
||||||
|
self.cx.app_states.insert(type_id, state);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
|
pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
|
||||||
where
|
where
|
||||||
T: Entity,
|
T: Entity,
|
||||||
|
@ -1828,6 +1856,10 @@ impl UpgradeModelHandle for MutableAppContext {
|
||||||
self.cx.upgrade_model_handle(handle)
|
self.cx.upgrade_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
|
||||||
|
self.cx.model_handle_is_upgradable(handle)
|
||||||
|
}
|
||||||
|
|
||||||
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
||||||
self.cx.upgrade_any_model_handle(handle)
|
self.cx.upgrade_any_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
@ -1898,6 +1930,7 @@ pub struct AppContext {
|
||||||
models: HashMap<usize, Box<dyn AnyModel>>,
|
models: HashMap<usize, Box<dyn AnyModel>>,
|
||||||
views: HashMap<(usize, usize), Box<dyn AnyView>>,
|
views: HashMap<(usize, usize), Box<dyn AnyView>>,
|
||||||
windows: HashMap<usize, Window>,
|
windows: HashMap<usize, Window>,
|
||||||
|
app_states: HashMap<TypeId, Box<dyn Any>>,
|
||||||
element_states: HashMap<ElementStateId, Box<dyn Any>>,
|
element_states: HashMap<ElementStateId, Box<dyn Any>>,
|
||||||
background: Arc<executor::Background>,
|
background: Arc<executor::Background>,
|
||||||
ref_counts: Arc<Mutex<RefCounts>>,
|
ref_counts: Arc<Mutex<RefCounts>>,
|
||||||
|
@ -1929,6 +1962,14 @@ impl AppContext {
|
||||||
pub fn platform(&self) -> &Arc<dyn Platform> {
|
pub fn platform(&self) -> &Arc<dyn Platform> {
|
||||||
&self.platform
|
&self.platform
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn app_state<T: 'static>(&self) -> &T {
|
||||||
|
self.app_states
|
||||||
|
.get(&TypeId::of::<T>())
|
||||||
|
.expect("no app state has been added for this type")
|
||||||
|
.downcast_ref()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadModel for AppContext {
|
impl ReadModel for AppContext {
|
||||||
|
@ -1956,6 +1997,10 @@ impl UpgradeModelHandle for AppContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
|
||||||
|
self.models.contains_key(&handle.model_id)
|
||||||
|
}
|
||||||
|
|
||||||
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
||||||
if self.models.contains_key(&handle.model_id) {
|
if self.models.contains_key(&handle.model_id) {
|
||||||
self.ref_counts.lock().inc_model(handle.model_id);
|
self.ref_counts.lock().inc_model(handle.model_id);
|
||||||
|
@ -2361,6 +2406,10 @@ impl<M> UpgradeModelHandle for ModelContext<'_, M> {
|
||||||
self.cx.upgrade_model_handle(handle)
|
self.cx.upgrade_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
|
||||||
|
self.cx.model_handle_is_upgradable(handle)
|
||||||
|
}
|
||||||
|
|
||||||
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
||||||
self.cx.upgrade_any_model_handle(handle)
|
self.cx.upgrade_any_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
@ -2699,6 +2748,10 @@ impl<V> UpgradeModelHandle for ViewContext<'_, V> {
|
||||||
self.cx.upgrade_model_handle(handle)
|
self.cx.upgrade_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
|
||||||
|
self.cx.model_handle_is_upgradable(handle)
|
||||||
|
}
|
||||||
|
|
||||||
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
||||||
self.cx.upgrade_any_model_handle(handle)
|
self.cx.upgrade_any_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
@ -2941,6 +2994,12 @@ impl<T> PartialEq for ModelHandle<T> {
|
||||||
|
|
||||||
impl<T> Eq for ModelHandle<T> {}
|
impl<T> Eq for ModelHandle<T> {}
|
||||||
|
|
||||||
|
impl<T> PartialEq<WeakModelHandle<T>> for ModelHandle<T> {
|
||||||
|
fn eq(&self, other: &WeakModelHandle<T>) -> bool {
|
||||||
|
self.model_id == other.model_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Hash for ModelHandle<T> {
|
impl<T> Hash for ModelHandle<T> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.model_id.hash(state);
|
self.model_id.hash(state);
|
||||||
|
@ -3013,6 +3072,10 @@ impl<T: Entity> WeakModelHandle<T> {
|
||||||
self.model_id
|
self.model_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_upgradable(&self, cx: &impl UpgradeModelHandle) -> bool {
|
||||||
|
cx.model_handle_is_upgradable(self)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<T>> {
|
pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<T>> {
|
||||||
cx.upgrade_model_handle(self)
|
cx.upgrade_model_handle(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,6 +281,10 @@ impl<'a> UpgradeModelHandle for LayoutContext<'a> {
|
||||||
self.app.upgrade_model_handle(handle)
|
self.app.upgrade_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
|
||||||
|
self.app.model_handle_is_upgradable(handle)
|
||||||
|
}
|
||||||
|
|
||||||
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
|
||||||
self.app.upgrade_any_model_handle(handle)
|
self.app.upgrade_any_model_handle(handle)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::{Direction, SearchOption, SelectMatch, ToggleSearchOption};
|
use crate::{Direction, SearchOption, SelectMatch, ToggleSearchOption};
|
||||||
|
use collections::HashMap;
|
||||||
use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll};
|
use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
action, elements::*, keymap::Binding, platform::CursorStyle, AppContext, ElementBox, Entity,
|
action, elements::*, keymap::Binding, platform::CursorStyle, AppContext, ElementBox, Entity,
|
||||||
ModelContext, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext,
|
ModelContext, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext,
|
||||||
ViewHandle,
|
ViewHandle, WeakModelHandle,
|
||||||
};
|
};
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use project::{search::SearchQuery, Project};
|
use project::{search::SearchQuery, Project};
|
||||||
|
@ -14,7 +15,9 @@ use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
use workspace::{Item, ItemHandle, ItemNavHistory, ItemView, Settings, Workspace};
|
use workspace::{
|
||||||
|
Item, ItemHandle, ItemNavHistory, ItemView, Settings, WeakItemViewHandle, Workspace,
|
||||||
|
};
|
||||||
|
|
||||||
action!(Deploy);
|
action!(Deploy);
|
||||||
action!(Search);
|
action!(Search);
|
||||||
|
@ -23,7 +26,11 @@ action!(ToggleFocus);
|
||||||
|
|
||||||
const MAX_TAB_TITLE_LEN: usize = 24;
|
const MAX_TAB_TITLE_LEN: usize = 24;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct ActiveSearches(HashMap<WeakModelHandle<Project>, WeakModelHandle<ProjectSearch>>);
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
|
cx.add_app_state(ActiveSearches::default());
|
||||||
cx.add_bindings([
|
cx.add_bindings([
|
||||||
Binding::new("cmd-shift-F", ToggleFocus, Some("ProjectSearchView")),
|
Binding::new("cmd-shift-F", ToggleFocus, Some("ProjectSearchView")),
|
||||||
Binding::new("cmd-f", ToggleFocus, Some("ProjectSearchView")),
|
Binding::new("cmd-f", ToggleFocus, Some("ProjectSearchView")),
|
||||||
|
@ -194,6 +201,13 @@ impl View for ProjectSearchView {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
cx.update_app_state(|state: &mut ActiveSearches, cx| {
|
||||||
|
state.0.insert(
|
||||||
|
self.model.read(cx).project.downgrade(),
|
||||||
|
self.model.downgrade(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
if self.model.read(cx).match_ranges.is_empty() {
|
if self.model.read(cx).match_ranges.is_empty() {
|
||||||
cx.focus(&self.query_editor);
|
cx.focus(&self.query_editor);
|
||||||
} else {
|
} else {
|
||||||
|
@ -383,11 +397,28 @@ impl ProjectSearchView {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-activate the most recently activated search or the most recent if it has been closed.
|
||||||
|
// If no search exists in the workspace, create a new one.
|
||||||
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
|
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
|
||||||
if let Some(existing) = workspace
|
// Clean up entries for dropped projects
|
||||||
.items_of_type::<ProjectSearch>(cx)
|
cx.update_app_state(|state: &mut ActiveSearches, cx| {
|
||||||
.max_by_key(|existing| existing.id())
|
state.0.retain(|project, _| project.is_upgradable(cx))
|
||||||
{
|
});
|
||||||
|
|
||||||
|
let active_search = cx
|
||||||
|
.app_state::<ActiveSearches>()
|
||||||
|
.0
|
||||||
|
.get(&workspace.project().downgrade());
|
||||||
|
|
||||||
|
let existing = active_search
|
||||||
|
.and_then(|active_search| {
|
||||||
|
workspace
|
||||||
|
.items_of_type::<ProjectSearch>(cx)
|
||||||
|
.find(|search| search == active_search)
|
||||||
|
})
|
||||||
|
.or_else(|| workspace.item_of_type::<ProjectSearch>(cx));
|
||||||
|
|
||||||
|
if let Some(existing) = existing {
|
||||||
workspace.activate_item(&existing, cx);
|
workspace.activate_item(&existing, cx);
|
||||||
} else {
|
} else {
|
||||||
let model = cx.add_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
|
let model = cx.add_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
|
||||||
|
@ -515,10 +546,7 @@ impl ProjectSearchView {
|
||||||
self.focus_results_editor(cx);
|
self.focus_results_editor(cx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.query_editor.update(cx, |query_editor, cx| {
|
self.focus_query_editor(cx);
|
||||||
query_editor.select_all(&SelectAll, cx);
|
|
||||||
});
|
|
||||||
cx.focus(&self.query_editor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,6 +560,13 @@ impl ProjectSearchView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_query_editor(&self, cx: &mut ViewContext<Self>) {
|
||||||
|
self.query_editor.update(cx, |query_editor, cx| {
|
||||||
|
query_editor.select_all(&SelectAll, cx);
|
||||||
|
});
|
||||||
|
cx.focus(&self.query_editor);
|
||||||
|
}
|
||||||
|
|
||||||
fn focus_results_editor(&self, cx: &mut ViewContext<Self>) {
|
fn focus_results_editor(&self, cx: &mut ViewContext<Self>) {
|
||||||
self.query_editor.update(cx, |query_editor, cx| {
|
self.query_editor.update(cx, |query_editor, cx| {
|
||||||
let cursor = query_editor.newest_anchor_selection().head();
|
let cursor = query_editor.newest_anchor_selection().head();
|
||||||
|
|
|
@ -9,7 +9,7 @@ mod status_bar;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use client::{Authenticate, ChannelList, Client, User, UserStore};
|
use client::{Authenticate, ChannelList, Client, User, UserStore};
|
||||||
use clock::ReplicaId;
|
use clock::ReplicaId;
|
||||||
use collections::HashSet;
|
use collections::BTreeMap;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
action,
|
action,
|
||||||
color::Color,
|
color::Color,
|
||||||
|
@ -36,6 +36,7 @@ pub use status_bar::StatusItemView;
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
cmp::Reverse,
|
||||||
future::Future,
|
future::Future,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
@ -569,7 +570,7 @@ pub struct Workspace {
|
||||||
status_bar: ViewHandle<StatusBar>,
|
status_bar: ViewHandle<StatusBar>,
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
path_openers: Arc<[Box<dyn PathOpener>]>,
|
path_openers: Arc<[Box<dyn PathOpener>]>,
|
||||||
items: HashSet<Box<dyn WeakItemHandle>>,
|
items: BTreeMap<Reverse<usize>, Box<dyn WeakItemHandle>>,
|
||||||
_observe_current_user: Task<()>,
|
_observe_current_user: Task<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,14 +816,14 @@ impl Workspace {
|
||||||
|
|
||||||
fn item_for_path(&self, path: &ProjectPath, cx: &AppContext) -> Option<Box<dyn ItemHandle>> {
|
fn item_for_path(&self, path: &ProjectPath, cx: &AppContext) -> Option<Box<dyn ItemHandle>> {
|
||||||
self.items
|
self.items
|
||||||
.iter()
|
.values()
|
||||||
.filter_map(|i| i.upgrade(cx))
|
.filter_map(|i| i.upgrade(cx))
|
||||||
.find(|i| i.project_path(cx).as_ref() == Some(path))
|
.find(|i| i.project_path(cx).as_ref() == Some(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn item_of_type<T: Item>(&self, cx: &AppContext) -> Option<ModelHandle<T>> {
|
pub fn item_of_type<T: Item>(&self, cx: &AppContext) -> Option<ModelHandle<T>> {
|
||||||
self.items
|
self.items
|
||||||
.iter()
|
.values()
|
||||||
.find_map(|i| i.upgrade(cx).and_then(|i| i.to_any().downcast()))
|
.find_map(|i| i.upgrade(cx).and_then(|i| i.to_any().downcast()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,7 +832,7 @@ impl Workspace {
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
) -> impl 'a + Iterator<Item = ModelHandle<T>> {
|
) -> impl 'a + Iterator<Item = ModelHandle<T>> {
|
||||||
self.items
|
self.items
|
||||||
.iter()
|
.values()
|
||||||
.filter_map(|i| i.upgrade(cx).and_then(|i| i.to_any().downcast()))
|
.filter_map(|i| i.upgrade(cx).and_then(|i| i.to_any().downcast()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,7 +975,8 @@ impl Workspace {
|
||||||
where
|
where
|
||||||
T: 'static + ItemHandle,
|
T: 'static + ItemHandle,
|
||||||
{
|
{
|
||||||
self.items.insert(item_handle.downgrade());
|
self.items
|
||||||
|
.insert(Reverse(item_handle.id()), item_handle.downgrade());
|
||||||
pane.update(cx, |pane, cx| pane.open_item(item_handle, self, cx))
|
pane.update(cx, |pane, cx| pane.open_item(item_handle, self, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1068,7 +1070,8 @@ impl Workspace {
|
||||||
if let Some(item) = pane.read(cx).active_item() {
|
if let Some(item) = pane.read(cx).active_item() {
|
||||||
let nav_history = new_pane.read(cx).nav_history().clone();
|
let nav_history = new_pane.read(cx).nav_history().clone();
|
||||||
if let Some(clone) = item.clone_on_split(nav_history, cx.as_mut()) {
|
if let Some(clone) = item.clone_on_split(nav_history, cx.as_mut()) {
|
||||||
self.items.insert(clone.item(cx).downgrade());
|
let item = clone.item(cx).downgrade();
|
||||||
|
self.items.insert(Reverse(item.id()), item);
|
||||||
new_pane.update(cx, |new_pane, cx| new_pane.add_item_view(clone, cx));
|
new_pane.update(cx, |new_pane, cx| new_pane.add_item_view(clone, cx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue