Start laying the foundation for a per-pane navigation system
This commit is contained in:
parent
cd0d1d3340
commit
bbf634f439
5 changed files with 135 additions and 16 deletions
|
@ -1,5 +1,6 @@
|
|||
use super::{ItemViewHandle, SplitDirection};
|
||||
use crate::{ItemHandle, Settings, Workspace};
|
||||
use crate::{ItemHandle, ItemView, Settings, WeakItemViewHandle, Workspace};
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
action,
|
||||
elements::*,
|
||||
|
@ -9,7 +10,8 @@ use gpui::{
|
|||
Entity, MutableAppContext, Quad, RenderContext, View, ViewContext,
|
||||
};
|
||||
use postage::watch;
|
||||
use std::cmp;
|
||||
use project::ProjectPath;
|
||||
use std::{any::Any, cell::RefCell, cmp, rc::Rc};
|
||||
|
||||
action!(Split, SplitDirection);
|
||||
action!(ActivateItem, usize);
|
||||
|
@ -17,6 +19,8 @@ action!(ActivatePrevItem);
|
|||
action!(ActivateNextItem);
|
||||
action!(CloseActiveItem);
|
||||
action!(CloseItem, usize);
|
||||
action!(GoBack);
|
||||
action!(GoForward);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(|pane: &mut Pane, action: &ActivateItem, cx| {
|
||||
|
@ -37,6 +41,8 @@ pub fn init(cx: &mut MutableAppContext) {
|
|||
cx.add_action(|pane: &mut Pane, action: &Split, cx| {
|
||||
pane.split(action.0, cx);
|
||||
});
|
||||
cx.add_action(Pane::go_back);
|
||||
cx.add_action(Pane::go_forward);
|
||||
|
||||
cx.add_bindings(vec![
|
||||
Binding::new("shift-cmd-{", ActivatePrevItem, Some("Pane")),
|
||||
|
@ -46,6 +52,8 @@ pub fn init(cx: &mut MutableAppContext) {
|
|||
Binding::new("cmd-k down", Split(SplitDirection::Down), Some("Pane")),
|
||||
Binding::new("cmd-k left", Split(SplitDirection::Left), Some("Pane")),
|
||||
Binding::new("cmd-k right", Split(SplitDirection::Right), Some("Pane")),
|
||||
Binding::new("ctrl-", GoBack, Some("Pane")),
|
||||
Binding::new("ctrl-shift-_", GoForward, Some("Pane")),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -61,6 +69,22 @@ pub struct Pane {
|
|||
item_views: Vec<(usize, Box<dyn ItemViewHandle>)>,
|
||||
active_item: usize,
|
||||
settings: watch::Receiver<Settings>,
|
||||
navigation: Rc<Navigation>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Navigation(RefCell<NavigationHistory>);
|
||||
|
||||
#[derive(Default)]
|
||||
struct NavigationHistory {
|
||||
backward_stack: Vec<NavigationEntry>,
|
||||
forward_stack: Vec<NavigationEntry>,
|
||||
paths_by_item: HashMap<usize, ProjectPath>,
|
||||
}
|
||||
|
||||
struct NavigationEntry {
|
||||
item_view: Box<dyn WeakItemViewHandle>,
|
||||
data: Option<Box<dyn Any>>,
|
||||
}
|
||||
|
||||
impl Pane {
|
||||
|
@ -69,6 +93,7 @@ impl Pane {
|
|||
item_views: Vec::new(),
|
||||
active_item: 0,
|
||||
settings,
|
||||
navigation: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +101,16 @@ impl Pane {
|
|||
cx.emit(Event::Activate);
|
||||
}
|
||||
|
||||
pub fn go_back(&mut self, _: &GoBack, cx: &mut ViewContext<Self>) {
|
||||
let mut navigation = self.navigation.0.borrow_mut();
|
||||
if let Some(entry) = navigation.go_back() {}
|
||||
}
|
||||
|
||||
pub fn go_forward(&mut self, _: &GoForward, cx: &mut ViewContext<Self>) {
|
||||
let mut navigation = self.navigation.0.borrow_mut();
|
||||
if let Some(entry) = navigation.go_forward() {}
|
||||
}
|
||||
|
||||
pub fn open_item<T>(
|
||||
&mut self,
|
||||
item_handle: T,
|
||||
|
@ -93,14 +128,15 @@ impl Pane {
|
|||
}
|
||||
}
|
||||
|
||||
let item_view = item_handle.add_view(cx.window_id(), workspace, cx);
|
||||
let item_view =
|
||||
item_handle.add_view(cx.window_id(), workspace, self.navigation.clone(), cx);
|
||||
self.add_item_view(item_view.boxed_clone(), cx);
|
||||
item_view
|
||||
}
|
||||
|
||||
pub fn add_item_view(
|
||||
&mut self,
|
||||
item_view: Box<dyn ItemViewHandle>,
|
||||
mut item_view: Box<dyn ItemViewHandle>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
item_view.added_to_pane(cx);
|
||||
|
@ -142,6 +178,7 @@ impl Pane {
|
|||
if index < self.item_views.len() {
|
||||
self.active_item = index;
|
||||
self.focus_active_item(cx);
|
||||
self.item_views[index].1.activated(cx);
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
@ -172,8 +209,21 @@ impl Pane {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn close_item(&mut self, item_id: usize, cx: &mut ViewContext<Self>) {
|
||||
self.item_views.retain(|(_, item)| item.id() != item_id);
|
||||
pub fn close_item(&mut self, item_view_id: usize, cx: &mut ViewContext<Self>) {
|
||||
self.item_views.retain(|(item_id, item)| {
|
||||
if item.id() == item_view_id {
|
||||
let mut navigation = self.navigation.0.borrow_mut();
|
||||
if let Some(path) = item.project_path(cx) {
|
||||
navigation.paths_by_item.insert(*item_id, path);
|
||||
} else {
|
||||
navigation.paths_by_item.remove(item_id);
|
||||
}
|
||||
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
self.active_item = cmp::min(self.active_item, self.item_views.len().saturating_sub(1));
|
||||
if self.item_views.is_empty() {
|
||||
cx.emit(Event::Remove);
|
||||
|
@ -369,3 +419,33 @@ impl View for Pane {
|
|||
self.focus_active_item(cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl Navigation {
|
||||
pub fn push<D: 'static + Any, T: ItemView>(&self, data: Option<D>, cx: &mut ViewContext<T>) {
|
||||
let mut state = self.0.borrow_mut();
|
||||
state.backward_stack.push(NavigationEntry {
|
||||
item_view: Box::new(cx.weak_handle()),
|
||||
data: data.map(|data| Box::new(data) as Box<dyn Any>),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl NavigationHistory {
|
||||
fn go_back(&mut self) -> Option<&NavigationEntry> {
|
||||
if let Some(backward) = self.backward_stack.pop() {
|
||||
self.forward_stack.push(backward);
|
||||
self.forward_stack.last()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn go_forward(&mut self) -> Option<&NavigationEntry> {
|
||||
if let Some(forward) = self.forward_stack.pop() {
|
||||
self.backward_stack.push(forward);
|
||||
self.backward_stack.last()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue