Checkpoint: Basic tab bar structure
This commit is contained in:
parent
5a41eed120
commit
8b1b7a2f80
3 changed files with 467 additions and 286 deletions
|
@ -1,7 +1,7 @@
|
||||||
// mod dragged_item_receiver;
|
// mod dragged_item_receiver;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
item::{Item, ItemHandle, WeakItemHandle},
|
item::{Item, ItemHandle, ItemSettings, WeakItemHandle},
|
||||||
toolbar::Toolbar,
|
toolbar::Toolbar,
|
||||||
workspace_settings::{AutosaveSetting, WorkspaceSettings},
|
workspace_settings::{AutosaveSetting, WorkspaceSettings},
|
||||||
SplitDirection, Workspace,
|
SplitDirection, Workspace,
|
||||||
|
@ -9,8 +9,8 @@ use crate::{
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::{HashMap, HashSet, VecDeque};
|
use collections::{HashMap, HashSet, VecDeque};
|
||||||
use gpui2::{
|
use gpui2::{
|
||||||
AppContext, AsyncWindowContext, EntityId, EventEmitter, Model, PromptLevel, Task, View,
|
AppContext, AsyncWindowContext, Component, Div, EntityId, EventEmitter, Model, PromptLevel,
|
||||||
ViewContext, VisualContext, WeakView, WindowContext,
|
Render, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use project2::{Project, ProjectEntryId, ProjectPath};
|
use project2::{Project, ProjectEntryId, ProjectPath};
|
||||||
|
@ -25,6 +25,8 @@ use std::{
|
||||||
Arc,
|
Arc,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use ui::{prelude::*, Icon, IconButton, IconColor, IconElement};
|
||||||
|
use ui::{v_stack};
|
||||||
use util::truncate_and_remove_front;
|
use util::truncate_and_remove_front;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, Deserialize, Debug)]
|
#[derive(PartialEq, Clone, Copy, Deserialize, Debug)]
|
||||||
|
@ -1345,6 +1347,162 @@ impl Pane {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_tab(
|
||||||
|
&self,
|
||||||
|
ix: usize,
|
||||||
|
item: &Box<dyn ItemHandle>,
|
||||||
|
detail: usize,
|
||||||
|
cx: &mut ViewContext<'_, Pane>,
|
||||||
|
) -> impl Component<Self> {
|
||||||
|
let label = item.tab_content(Some(detail), cx);
|
||||||
|
|
||||||
|
// let label = match (self.git_status, is_deleted) {
|
||||||
|
// (_, true) | (GitStatus::Deleted, false) => Label::new(self.title.clone())
|
||||||
|
// .color(LabelColor::Hidden)
|
||||||
|
// .set_strikethrough(true),
|
||||||
|
// (GitStatus::None, false) => Label::new(self.title.clone()),
|
||||||
|
// (GitStatus::Created, false) => {
|
||||||
|
// Label::new(self.title.clone()).color(LabelColor::Created)
|
||||||
|
// }
|
||||||
|
// (GitStatus::Modified, false) => {
|
||||||
|
// Label::new(self.title.clone()).color(LabelColor::Modified)
|
||||||
|
// }
|
||||||
|
// (GitStatus::Renamed, false) => Label::new(self.title.clone()).color(LabelColor::Accent),
|
||||||
|
// (GitStatus::Conflict, false) => Label::new(self.title.clone()),
|
||||||
|
// };
|
||||||
|
|
||||||
|
let close_icon = || IconElement::new(Icon::Close).color(IconColor::Muted);
|
||||||
|
|
||||||
|
let (tab_bg, tab_hover_bg, tab_active_bg) = match ix == self.active_item_index {
|
||||||
|
false => (
|
||||||
|
cx.theme().colors().tab_inactive,
|
||||||
|
cx.theme().colors().ghost_element_hover,
|
||||||
|
cx.theme().colors().ghost_element_active,
|
||||||
|
),
|
||||||
|
true => (
|
||||||
|
cx.theme().colors().tab_active,
|
||||||
|
cx.theme().colors().element_hover,
|
||||||
|
cx.theme().colors().element_active,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let close_right = ItemSettings::get_global(cx).close_position.right();
|
||||||
|
|
||||||
|
div()
|
||||||
|
.id(item.id())
|
||||||
|
// .on_drag(move |pane, cx| pane.render_tab(ix, item.boxed_clone(), detail, cx))
|
||||||
|
// .drag_over::<DraggedTab>(|d| d.bg(cx.theme().colors().element_drop_target))
|
||||||
|
// .on_drop(|_view, state: View<DraggedTab>, cx| {
|
||||||
|
// eprintln!("{:?}", state.read(cx));
|
||||||
|
// })
|
||||||
|
.px_2()
|
||||||
|
.py_0p5()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_center()
|
||||||
|
.bg(tab_bg)
|
||||||
|
.hover(|h| h.bg(tab_hover_bg))
|
||||||
|
.active(|a| a.bg(tab_active_bg))
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.px_1()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_1p5()
|
||||||
|
.children(if item.has_conflict(cx) {
|
||||||
|
Some(
|
||||||
|
IconElement::new(Icon::ExclamationTriangle)
|
||||||
|
.size(ui::IconSize::Small)
|
||||||
|
.color(IconColor::Warning),
|
||||||
|
)
|
||||||
|
} else if item.is_dirty(cx) {
|
||||||
|
Some(
|
||||||
|
IconElement::new(Icon::ExclamationTriangle)
|
||||||
|
.size(ui::IconSize::Small)
|
||||||
|
.color(IconColor::Info),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.children(if !close_right {
|
||||||
|
Some(close_icon())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.child(label)
|
||||||
|
.children(if close_right {
|
||||||
|
Some(close_icon())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_tab_bar(&mut self, cx: &mut ViewContext<'_, Pane>) -> impl Component<Self> {
|
||||||
|
div()
|
||||||
|
.group("tab_bar")
|
||||||
|
.id("tab_bar")
|
||||||
|
.w_full()
|
||||||
|
.flex()
|
||||||
|
.bg(cx.theme().colors().tab_bar)
|
||||||
|
// Left Side
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.relative()
|
||||||
|
.px_1()
|
||||||
|
.flex()
|
||||||
|
.flex_none()
|
||||||
|
.gap_2()
|
||||||
|
// Nav Buttons
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.right_0()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_px()
|
||||||
|
.child(IconButton::new("navigate_backward", Icon::ArrowLeft).state(
|
||||||
|
InteractionState::Enabled.if_enabled(self.can_navigate_backward()),
|
||||||
|
))
|
||||||
|
.child(IconButton::new("navigate_forward", Icon::ArrowRight).state(
|
||||||
|
InteractionState::Enabled.if_enabled(self.can_navigate_forward()),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div().w_0().flex_1().h_full().child(
|
||||||
|
div().id("tabs").flex().overflow_x_scroll().children(
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.zip(self.tab_details(cx))
|
||||||
|
.map(|((ix, item), detail)| self.render_tab(ix, item, detail, cx)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// Right Side
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
// We only use absolute here since we don't
|
||||||
|
// have opacity or `hidden()` yet
|
||||||
|
.absolute()
|
||||||
|
.neg_top_7()
|
||||||
|
.px_1()
|
||||||
|
.flex()
|
||||||
|
.flex_none()
|
||||||
|
.gap_2()
|
||||||
|
.group_hover("tab_bar", |this| this.top_0())
|
||||||
|
// Nav Buttons
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_px()
|
||||||
|
.child(IconButton::new("plus", Icon::Plus))
|
||||||
|
.child(IconButton::new("split", Icon::Split)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// fn render_tabs(&mut self, cx: &mut ViewContext<Self>) -> impl Element<Self> {
|
// fn render_tabs(&mut self, cx: &mut ViewContext<Self>) -> impl Element<Self> {
|
||||||
// let theme = theme::current(cx).clone();
|
// let theme = theme::current(cx).clone();
|
||||||
|
|
||||||
|
@ -1500,42 +1658,42 @@ impl Pane {
|
||||||
// row
|
// row
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// fn tab_details(&self, cx: &AppContext) -> Vec<usize> {
|
fn tab_details(&self, cx: &AppContext) -> Vec<usize> {
|
||||||
// let mut tab_details = (0..self.items.len()).map(|_| 0).collect::<Vec<_>>();
|
let mut tab_details = self.items.iter().map(|_| 0).collect::<Vec<_>>();
|
||||||
|
|
||||||
// let mut tab_descriptions = HashMap::default();
|
let mut tab_descriptions = HashMap::default();
|
||||||
// let mut done = false;
|
let mut done = false;
|
||||||
// while !done {
|
while !done {
|
||||||
// done = true;
|
done = true;
|
||||||
|
|
||||||
// // Store item indices by their tab description.
|
// Store item indices by their tab description.
|
||||||
// for (ix, (item, detail)) in self.items.iter().zip(&tab_details).enumerate() {
|
for (ix, (item, detail)) in self.items.iter().zip(&tab_details).enumerate() {
|
||||||
// if let Some(description) = item.tab_description(*detail, cx) {
|
if let Some(description) = item.tab_description(*detail, cx) {
|
||||||
// if *detail == 0
|
if *detail == 0
|
||||||
// || Some(&description) != item.tab_description(detail - 1, cx).as_ref()
|
|| Some(&description) != item.tab_description(detail - 1, cx).as_ref()
|
||||||
// {
|
{
|
||||||
// tab_descriptions
|
tab_descriptions
|
||||||
// .entry(description)
|
.entry(description)
|
||||||
// .or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
// .push(ix);
|
.push(ix);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // If two or more items have the same tab description, increase their level
|
// If two or more items have the same tab description, increase eir level
|
||||||
// // of detail and try again.
|
// of detail and try again.
|
||||||
// for (_, item_ixs) in tab_descriptions.drain() {
|
for (_, item_ixs) in tab_descriptions.drain() {
|
||||||
// if item_ixs.len() > 1 {
|
if item_ixs.len() > 1 {
|
||||||
// done = false;
|
done = false;
|
||||||
// for ix in item_ixs {
|
for ix in item_ixs {
|
||||||
// tab_details[ix] += 1;
|
tab_details[ix] += 1;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// tab_details
|
tab_details
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn render_tab(
|
// fn render_tab(
|
||||||
// item: &Box<dyn ItemHandle>,
|
// item: &Box<dyn ItemHandle>,
|
||||||
|
@ -1737,237 +1895,243 @@ impl Pane {
|
||||||
// type Event = Event;
|
// type Event = Event;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// impl View for Pane {
|
impl Render for Pane {
|
||||||
// fn ui_name() -> &'static str {
|
type Element = Div<Self>;
|
||||||
// "Pane"
|
// fn ui_name() -> &'static str {
|
||||||
// }
|
// "Pane"
|
||||||
|
// }
|
||||||
|
|
||||||
// fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
// enum MouseNavigationHandler {}
|
v_stack()
|
||||||
|
.child(self.render_tab_bar(cx))
|
||||||
|
.child(div() /* toolbar */)
|
||||||
|
.child(div() /* active item */)
|
||||||
|
|
||||||
// MouseEventHandler::new::<MouseNavigationHandler, _>(0, cx, |_, cx| {
|
// enum MouseNavigationHandler {}
|
||||||
// let active_item_index = self.active_item_index;
|
|
||||||
|
|
||||||
// if let Some(active_item) = self.active_item() {
|
// MouseEventHandler::new::<MouseNavigationHandler, _>(0, cx, |_, cx| {
|
||||||
// Flex::column()
|
// let active_item_index = self.active_item_index;
|
||||||
// .with_child({
|
|
||||||
// let theme = theme::current(cx).clone();
|
|
||||||
|
|
||||||
// let mut stack = Stack::new();
|
// if let Some(active_item) = self.active_item() {
|
||||||
|
// Flex::column()
|
||||||
|
// .with_child({
|
||||||
|
// let theme = theme::current(cx).clone();
|
||||||
|
|
||||||
// enum TabBarEventHandler {}
|
// let mut stack = Stack::new();
|
||||||
// stack.add_child(
|
|
||||||
// MouseEventHandler::new::<TabBarEventHandler, _>(0, cx, |_, _| {
|
|
||||||
// Empty::new()
|
|
||||||
// .contained()
|
|
||||||
// .with_style(theme.workspace.tab_bar.container)
|
|
||||||
// })
|
|
||||||
// .on_down(
|
|
||||||
// MouseButton::Left,
|
|
||||||
// move |_, this, cx| {
|
|
||||||
// this.activate_item(active_item_index, true, true, cx);
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// let tooltip_style = theme.tooltip.clone();
|
|
||||||
// let tab_bar_theme = theme.workspace.tab_bar.clone();
|
|
||||||
|
|
||||||
// let nav_button_height = tab_bar_theme.height;
|
// enum TabBarEventHandler {}
|
||||||
// let button_style = tab_bar_theme.nav_button;
|
// stack.add_child(
|
||||||
// let border_for_nav_buttons = tab_bar_theme
|
// MouseEventHandler::new::<TabBarEventHandler, _>(0, cx, |_, _| {
|
||||||
// .tab_style(false, false)
|
// Empty::new()
|
||||||
// .container
|
// .contained()
|
||||||
// .border
|
// .with_style(theme.workspace.tab_bar.container)
|
||||||
// .clone();
|
// })
|
||||||
|
// .on_down(
|
||||||
|
// MouseButton::Left,
|
||||||
|
// move |_, this, cx| {
|
||||||
|
// this.activate_item(active_item_index, true, true, cx);
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// let tooltip_style = theme.tooltip.clone();
|
||||||
|
// let tab_bar_theme = theme.workspace.tab_bar.clone();
|
||||||
|
|
||||||
// let mut tab_row = Flex::row()
|
// let nav_button_height = tab_bar_theme.height;
|
||||||
// .with_child(nav_button(
|
// let button_style = tab_bar_theme.nav_button;
|
||||||
// "icons/arrow_left.svg",
|
// let border_for_nav_buttons = tab_bar_theme
|
||||||
// button_style.clone(),
|
// .tab_style(false, false)
|
||||||
// nav_button_height,
|
// .container
|
||||||
// tooltip_style.clone(),
|
// .border
|
||||||
// self.can_navigate_backward(),
|
// .clone();
|
||||||
// {
|
|
||||||
// move |pane, cx| {
|
|
||||||
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
|
||||||
// let pane = cx.weak_handle();
|
|
||||||
// cx.window_context().defer(move |cx| {
|
|
||||||
// workspace.update(cx, |workspace, cx| {
|
|
||||||
// workspace
|
|
||||||
// .go_back(pane, cx)
|
|
||||||
// .detach_and_log_err(cx)
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// super::GoBack,
|
|
||||||
// "Go Back",
|
|
||||||
// cx,
|
|
||||||
// ))
|
|
||||||
// .with_child(
|
|
||||||
// nav_button(
|
|
||||||
// "icons/arrow_right.svg",
|
|
||||||
// button_style.clone(),
|
|
||||||
// nav_button_height,
|
|
||||||
// tooltip_style,
|
|
||||||
// self.can_navigate_forward(),
|
|
||||||
// {
|
|
||||||
// move |pane, cx| {
|
|
||||||
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
|
||||||
// let pane = cx.weak_handle();
|
|
||||||
// cx.window_context().defer(move |cx| {
|
|
||||||
// workspace.update(cx, |workspace, cx| {
|
|
||||||
// workspace
|
|
||||||
// .go_forward(pane, cx)
|
|
||||||
// .detach_and_log_err(cx)
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// super::GoForward,
|
|
||||||
// "Go Forward",
|
|
||||||
// cx,
|
|
||||||
// )
|
|
||||||
// .contained()
|
|
||||||
// .with_border(border_for_nav_buttons),
|
|
||||||
// )
|
|
||||||
// .with_child(self.render_tabs(cx).flex(1., true).into_any_named("tabs"));
|
|
||||||
|
|
||||||
// if self.has_focus {
|
// let mut tab_row = Flex::row()
|
||||||
// let render_tab_bar_buttons = self.render_tab_bar_buttons.clone();
|
// .with_child(nav_button(
|
||||||
// tab_row.add_child(
|
// "icons/arrow_left.svg",
|
||||||
// (render_tab_bar_buttons)(self, cx)
|
// button_style.clone(),
|
||||||
// .contained()
|
// nav_button_height,
|
||||||
// .with_style(theme.workspace.tab_bar.pane_button_container)
|
// tooltip_style.clone(),
|
||||||
// .flex(1., false)
|
// self.can_navigate_backward(),
|
||||||
// .into_any(),
|
// {
|
||||||
// )
|
// move |pane, cx| {
|
||||||
// }
|
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
||||||
|
// let pane = cx.weak_handle();
|
||||||
|
// cx.window_context().defer(move |cx| {
|
||||||
|
// workspace.update(cx, |workspace, cx| {
|
||||||
|
// workspace
|
||||||
|
// .go_back(pane, cx)
|
||||||
|
// .detach_and_log_err(cx)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// super::GoBack,
|
||||||
|
// "Go Back",
|
||||||
|
// cx,
|
||||||
|
// ))
|
||||||
|
// .with_child(
|
||||||
|
// nav_button(
|
||||||
|
// "icons/arrow_right.svg",
|
||||||
|
// button_style.clone(),
|
||||||
|
// nav_button_height,
|
||||||
|
// tooltip_style,
|
||||||
|
// self.can_navigate_forward(),
|
||||||
|
// {
|
||||||
|
// move |pane, cx| {
|
||||||
|
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
||||||
|
// let pane = cx.weak_handle();
|
||||||
|
// cx.window_context().defer(move |cx| {
|
||||||
|
// workspace.update(cx, |workspace, cx| {
|
||||||
|
// workspace
|
||||||
|
// .go_forward(pane, cx)
|
||||||
|
// .detach_and_log_err(cx)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// super::GoForward,
|
||||||
|
// "Go Forward",
|
||||||
|
// cx,
|
||||||
|
// )
|
||||||
|
// .contained()
|
||||||
|
// .with_border(border_for_nav_buttons),
|
||||||
|
// )
|
||||||
|
// .with_child(self.render_tabs(cx).flex(1., true).into_any_named("tabs"));
|
||||||
|
|
||||||
// stack.add_child(tab_row);
|
// if self.has_focus {
|
||||||
// stack
|
// let render_tab_bar_buttons = self.render_tab_bar_buttons.clone();
|
||||||
// .constrained()
|
// tab_row.add_child(
|
||||||
// .with_height(theme.workspace.tab_bar.height)
|
// (render_tab_bar_buttons)(self, cx)
|
||||||
// .flex(1., false)
|
// .contained()
|
||||||
// .into_any_named("tab bar")
|
// .with_style(theme.workspace.tab_bar.pane_button_container)
|
||||||
// })
|
// .flex(1., false)
|
||||||
// .with_child({
|
// .into_any(),
|
||||||
// enum PaneContentTabDropTarget {}
|
// )
|
||||||
// dragged_item_receiver::<PaneContentTabDropTarget, _, _>(
|
// }
|
||||||
// self,
|
|
||||||
// 0,
|
|
||||||
// self.active_item_index + 1,
|
|
||||||
// !self.can_split,
|
|
||||||
// if self.can_split { Some(100.) } else { None },
|
|
||||||
// cx,
|
|
||||||
// {
|
|
||||||
// let toolbar = self.toolbar.clone();
|
|
||||||
// let toolbar_hidden = toolbar.read(cx).hidden();
|
|
||||||
// move |_, cx| {
|
|
||||||
// Flex::column()
|
|
||||||
// .with_children(
|
|
||||||
// (!toolbar_hidden)
|
|
||||||
// .then(|| ChildView::new(&toolbar, cx).expanded()),
|
|
||||||
// )
|
|
||||||
// .with_child(
|
|
||||||
// ChildView::new(active_item.as_any(), cx).flex(1., true),
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
// .flex(1., true)
|
|
||||||
// })
|
|
||||||
// .with_child(ChildView::new(&self.tab_context_menu, cx))
|
|
||||||
// .into_any()
|
|
||||||
// } else {
|
|
||||||
// enum EmptyPane {}
|
|
||||||
// let theme = theme::current(cx).clone();
|
|
||||||
|
|
||||||
// dragged_item_receiver::<EmptyPane, _, _>(self, 0, 0, false, None, cx, |_, cx| {
|
// stack.add_child(tab_row);
|
||||||
// self.render_blank_pane(&theme, cx)
|
// stack
|
||||||
// })
|
// .constrained()
|
||||||
// .on_down(MouseButton::Left, |_, _, cx| {
|
// .with_height(theme.workspace.tab_bar.height)
|
||||||
// cx.focus_parent();
|
// .flex(1., false)
|
||||||
// })
|
// .into_any_named("tab bar")
|
||||||
// .into_any()
|
// })
|
||||||
// }
|
// .with_child({
|
||||||
// })
|
// enum PaneContentTabDropTarget {}
|
||||||
// .on_down(
|
// dragged_item_receiver::<PaneContentTabDropTarget, _, _>(
|
||||||
// MouseButton::Navigate(NavigationDirection::Back),
|
// self,
|
||||||
// move |_, pane, cx| {
|
// 0,
|
||||||
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
// self.active_item_index + 1,
|
||||||
// let pane = cx.weak_handle();
|
// !self.can_split,
|
||||||
// cx.window_context().defer(move |cx| {
|
// if self.can_split { Some(100.) } else { None },
|
||||||
// workspace.update(cx, |workspace, cx| {
|
// cx,
|
||||||
// workspace.go_back(pane, cx).detach_and_log_err(cx)
|
// {
|
||||||
// })
|
// let toolbar = self.toolbar.clone();
|
||||||
// })
|
// let toolbar_hidden = toolbar.read(cx).hidden();
|
||||||
// }
|
// move |_, cx| {
|
||||||
// },
|
// Flex::column()
|
||||||
// )
|
// .with_children(
|
||||||
// .on_down(MouseButton::Navigate(NavigationDirection::Forward), {
|
// (!toolbar_hidden)
|
||||||
// move |_, pane, cx| {
|
// .then(|| ChildView::new(&toolbar, cx).expanded()),
|
||||||
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
// )
|
||||||
// let pane = cx.weak_handle();
|
// .with_child(
|
||||||
// cx.window_context().defer(move |cx| {
|
// ChildView::new(active_item.as_any(), cx).flex(1., true),
|
||||||
// workspace.update(cx, |workspace, cx| {
|
// )
|
||||||
// workspace.go_forward(pane, cx).detach_and_log_err(cx)
|
// }
|
||||||
// })
|
// },
|
||||||
// })
|
// )
|
||||||
// }
|
// .flex(1., true)
|
||||||
// }
|
// })
|
||||||
// })
|
// .with_child(ChildView::new(&self.tab_context_menu, cx))
|
||||||
// .into_any_named("pane")
|
// .into_any()
|
||||||
// }
|
// } else {
|
||||||
|
// enum EmptyPane {}
|
||||||
|
// let theme = theme::current(cx).clone();
|
||||||
|
|
||||||
// fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
// dragged_item_receiver::<EmptyPane, _, _>(self, 0, 0, false, None, cx, |_, cx| {
|
||||||
// if !self.has_focus {
|
// self.render_blank_pane(&theme, cx)
|
||||||
// self.has_focus = true;
|
// })
|
||||||
// cx.emit(Event::Focus);
|
// .on_down(MouseButton::Left, |_, _, cx| {
|
||||||
// cx.notify();
|
// cx.focus_parent();
|
||||||
// }
|
// })
|
||||||
|
// .into_any()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .on_down(
|
||||||
|
// MouseButton::Navigate(NavigationDirection::Back),
|
||||||
|
// move |_, pane, cx| {
|
||||||
|
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
||||||
|
// let pane = cx.weak_handle();
|
||||||
|
// cx.window_context().defer(move |cx| {
|
||||||
|
// workspace.update(cx, |workspace, cx| {
|
||||||
|
// workspace.go_back(pane, cx).detach_and_log_err(cx)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// )
|
||||||
|
// .on_down(MouseButton::Navigate(NavigationDirection::Forward), {
|
||||||
|
// move |_, pane, cx| {
|
||||||
|
// if let Some(workspace) = pane.workspace.upgrade(cx) {
|
||||||
|
// let pane = cx.weak_handle();
|
||||||
|
// cx.window_context().defer(move |cx| {
|
||||||
|
// workspace.update(cx, |workspace, cx| {
|
||||||
|
// workspace.go_forward(pane, cx).detach_and_log_err(cx)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .into_any_named("pane")
|
||||||
|
}
|
||||||
|
|
||||||
// self.toolbar.update(cx, |toolbar, cx| {
|
// fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
// toolbar.focus_changed(true, cx);
|
// if !self.has_focus {
|
||||||
// });
|
// self.has_focus = true;
|
||||||
|
// cx.emit(Event::Focus);
|
||||||
|
// cx.notify();
|
||||||
|
// }
|
||||||
|
|
||||||
// if let Some(active_item) = self.active_item() {
|
// self.toolbar.update(cx, |toolbar, cx| {
|
||||||
// if cx.is_self_focused() {
|
// toolbar.focus_changed(true, cx);
|
||||||
// // Pane was focused directly. We need to either focus a view inside the active item,
|
// });
|
||||||
// // or focus the active item itself
|
|
||||||
// if let Some(weak_last_focused_view) =
|
|
||||||
// self.last_focused_view_by_item.get(&active_item.id())
|
|
||||||
// {
|
|
||||||
// if let Some(last_focused_view) = weak_last_focused_view.upgrade(cx) {
|
|
||||||
// cx.focus(&last_focused_view);
|
|
||||||
// return;
|
|
||||||
// } else {
|
|
||||||
// self.last_focused_view_by_item.remove(&active_item.id());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// cx.focus(active_item.as_any());
|
// if let Some(active_item) = self.active_item() {
|
||||||
// } else if focused != self.tab_bar_context_menu.handle {
|
// if cx.is_self_focused() {
|
||||||
// self.last_focused_view_by_item
|
// // Pane was focused directly. We need to either focus a view inside the active item,
|
||||||
// .insert(active_item.id(), focused.downgrade());
|
// // or focus the active item itself
|
||||||
// }
|
// if let Some(weak_last_focused_view) =
|
||||||
// }
|
// self.last_focused_view_by_item.get(&active_item.id())
|
||||||
// }
|
// {
|
||||||
|
// if let Some(last_focused_view) = weak_last_focused_view.upgrade(cx) {
|
||||||
|
// cx.focus(&last_focused_view);
|
||||||
|
// return;
|
||||||
|
// } else {
|
||||||
|
// self.last_focused_view_by_item.remove(&active_item.id());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
// cx.focus(active_item.as_any());
|
||||||
// self.has_focus = false;
|
// } else if focused != self.tab_bar_context_menu.handle {
|
||||||
// self.toolbar.update(cx, |toolbar, cx| {
|
// self.last_focused_view_by_item
|
||||||
// toolbar.focus_changed(false, cx);
|
// .insert(active_item.id(), focused.downgrade());
|
||||||
// });
|
// }
|
||||||
// cx.notify();
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
|
// fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
// Self::reset_to_default_keymap_context(keymap);
|
// self.has_focus = false;
|
||||||
// }
|
// self.toolbar.update(cx, |toolbar, cx| {
|
||||||
// }
|
// toolbar.focus_changed(false, cx);
|
||||||
|
// });
|
||||||
|
// cx.notify();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
|
||||||
|
// Self::reset_to_default_keymap_context(keymap);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
impl ItemNavHistory {
|
impl ItemNavHistory {
|
||||||
pub fn push<D: 'static + Send + Any>(&mut self, data: Option<D>, cx: &mut WindowContext) {
|
pub fn push<D: 'static + Send + Any>(&mut self, data: Option<D>, cx: &mut WindowContext) {
|
||||||
|
@ -2747,3 +2911,16 @@ fn dirty_message_for(buffer_path: Option<ProjectPath>) -> String {
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct DraggedTab {
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for DraggedTab {
|
||||||
|
type Element = Div<Self>;
|
||||||
|
|
||||||
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
|
div().w_8().h_4().bg(gpui2::red())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,12 +6,13 @@ use db2::sqlez::{
|
||||||
bindable::{Bind, Column, StaticColumnCount},
|
bindable::{Bind, Column, StaticColumnCount},
|
||||||
statement::Statement,
|
statement::Statement,
|
||||||
};
|
};
|
||||||
use gpui2::{point, size, AnyElement, AnyView, Bounds, Model, Pixels, Point, View, ViewContext};
|
use gpui2::{
|
||||||
|
point, size, AnyElement, AnyView, AnyWeakView, Bounds, Model, Pixels, Point, View, ViewContext,
|
||||||
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use project2::Project;
|
use project2::Project;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use theme2::ThemeVariant;
|
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
const HANDLE_HITBOX_SIZE: f32 = 4.0;
|
const HANDLE_HITBOX_SIZE: f32 = 4.0;
|
||||||
|
@ -128,10 +129,10 @@ impl PaneGroup {
|
||||||
follower_states: &HashMap<View<Pane>, FollowerState>,
|
follower_states: &HashMap<View<Pane>, FollowerState>,
|
||||||
active_call: Option<&Model<ActiveCall>>,
|
active_call: Option<&Model<ActiveCall>>,
|
||||||
active_pane: &View<Pane>,
|
active_pane: &View<Pane>,
|
||||||
zoomed: Option<&AnyView>,
|
zoomed: Option<&AnyWeakView>,
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> AnyElement<Workspace> {
|
) -> impl Component<Workspace> {
|
||||||
self.root.render(
|
self.root.render(
|
||||||
project,
|
project,
|
||||||
0,
|
0,
|
||||||
|
@ -189,36 +190,38 @@ impl Member {
|
||||||
follower_states: &HashMap<View<Pane>, FollowerState>,
|
follower_states: &HashMap<View<Pane>, FollowerState>,
|
||||||
active_call: Option<&Model<ActiveCall>>,
|
active_call: Option<&Model<ActiveCall>>,
|
||||||
active_pane: &View<Pane>,
|
active_pane: &View<Pane>,
|
||||||
zoomed: Option<&AnyView>,
|
zoomed: Option<&AnyWeakView>,
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> AnyElement<Workspace> {
|
) -> impl Component<Workspace> {
|
||||||
match self {
|
match self {
|
||||||
Member::Pane(pane) => {
|
Member::Pane(pane) => {
|
||||||
let pane_element = if Some(&**pane) == zoomed {
|
// todo!()
|
||||||
None
|
// let pane_element = if Some(pane.into()) == zoomed {
|
||||||
} else {
|
// None
|
||||||
Some(pane)
|
// } else {
|
||||||
};
|
// Some(pane)
|
||||||
|
// };
|
||||||
|
|
||||||
|
div().child(pane.clone()).render()
|
||||||
|
|
||||||
// Stack::new()
|
// Stack::new()
|
||||||
// .with_child(pane_element.contained().with_border(leader_border))
|
// .with_child(pane_element.contained().with_border(leader_border))
|
||||||
// .with_children(leader_status_box)
|
// .with_children(leader_status_box)
|
||||||
// .into_any()
|
// .into_any()
|
||||||
|
|
||||||
let el = div()
|
// let el = div()
|
||||||
.flex()
|
// .flex()
|
||||||
.flex_1()
|
// .flex_1()
|
||||||
.gap_px()
|
// .gap_px()
|
||||||
.w_full()
|
// .w_full()
|
||||||
.h_full()
|
// .h_full()
|
||||||
.bg(cx.theme().colors().editor)
|
// .bg(cx.theme().colors().editor)
|
||||||
.children();
|
// .children();
|
||||||
}
|
}
|
||||||
Member::Axis(axis) => axis.render(
|
Member::Axis(axis) => axis.render(
|
||||||
project,
|
project,
|
||||||
basis + 1,
|
basis + 1,
|
||||||
theme,
|
|
||||||
follower_states,
|
follower_states,
|
||||||
active_call,
|
active_call,
|
||||||
active_pane,
|
active_pane,
|
||||||
|
@ -541,11 +544,10 @@ impl PaneAxis {
|
||||||
&self,
|
&self,
|
||||||
project: &Model<Project>,
|
project: &Model<Project>,
|
||||||
basis: usize,
|
basis: usize,
|
||||||
theme: &ThemeVariant,
|
|
||||||
follower_states: &HashMap<View<Pane>, FollowerState>,
|
follower_states: &HashMap<View<Pane>, FollowerState>,
|
||||||
active_call: Option<&Model<ActiveCall>>,
|
active_call: Option<&Model<ActiveCall>>,
|
||||||
active_pane: &View<Pane>,
|
active_pane: &View<Pane>,
|
||||||
zoomed: Option<&AnyView>,
|
zoomed: Option<&AnyWeakView>,
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> AnyElement<Workspace> {
|
) -> AnyElement<Workspace> {
|
||||||
|
|
|
@ -28,10 +28,11 @@ use futures::{
|
||||||
Future, FutureExt, StreamExt,
|
Future, FutureExt, StreamExt,
|
||||||
};
|
};
|
||||||
use gpui2::{
|
use gpui2::{
|
||||||
div, point, size, AnyModel, AnyView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds,
|
div, point, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext,
|
||||||
Component, Div, Element, EntityId, EventEmitter, GlobalPixels, Model, ModelContext,
|
AsyncWindowContext, Bounds, Component, Div, EntityId, EventEmitter, GlobalPixels,
|
||||||
ParentElement, Point, Render, Size, StatefulInteractive, Styled, Subscription, Task, View,
|
Model, ModelContext, ParentElement, Point, Render, Size, StatefulInteractive, Styled,
|
||||||
ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext,
|
||||||
|
WindowHandle, WindowOptions,
|
||||||
};
|
};
|
||||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||||
use language2::LanguageRegistry;
|
use language2::LanguageRegistry;
|
||||||
|
@ -544,7 +545,7 @@ pub enum Event {
|
||||||
pub struct Workspace {
|
pub struct Workspace {
|
||||||
weak_self: WeakView<Self>,
|
weak_self: WeakView<Self>,
|
||||||
// modal: Option<ActiveModal>,
|
// modal: Option<ActiveModal>,
|
||||||
// zoomed: Option<AnyWeakViewHandle>,
|
zoomed: Option<AnyWeakView>,
|
||||||
// zoomed_position: Option<DockPosition>,
|
// zoomed_position: Option<DockPosition>,
|
||||||
center: PaneGroup,
|
center: PaneGroup,
|
||||||
left_dock: View<Dock>,
|
left_dock: View<Dock>,
|
||||||
|
@ -622,7 +623,7 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
project2::Event::Closed => {
|
project2::Event::Closed => {
|
||||||
cx.remove_window();
|
// cx.remove_window();
|
||||||
}
|
}
|
||||||
|
|
||||||
project2::Event::DeletedEntry(entry_id) => {
|
project2::Event::DeletedEntry(entry_id) => {
|
||||||
|
@ -763,7 +764,7 @@ impl Workspace {
|
||||||
Workspace {
|
Workspace {
|
||||||
weak_self: weak_handle.clone(),
|
weak_self: weak_handle.clone(),
|
||||||
// modal: None,
|
// modal: None,
|
||||||
// zoomed: None,
|
zoomed: None,
|
||||||
// zoomed_position: None,
|
// zoomed_position: None,
|
||||||
center: PaneGroup::new(center_pane.clone()),
|
center: PaneGroup::new(center_pane.clone()),
|
||||||
panes: vec![center_pane.clone()],
|
panes: vec![center_pane.clone()],
|
||||||
|
@ -2698,7 +2699,8 @@ impl Workspace {
|
||||||
.id("titlebar")
|
.id("titlebar")
|
||||||
.on_click(|workspace, event, cx| {
|
.on_click(|workspace, event, cx| {
|
||||||
if event.up.click_count == 2 {
|
if event.up.click_count == 2 {
|
||||||
cx.zoom_window();
|
// todo!()
|
||||||
|
// cx.zoom_window();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.child("Collab title bar Item") // self.titlebar_item
|
.child("Collab title bar Item") // self.titlebar_item
|
||||||
|
@ -3805,12 +3807,12 @@ impl Render for Workspace {
|
||||||
.child(
|
.child(
|
||||||
div().flex().flex_col().flex_1().h_full().child(
|
div().flex().flex_col().flex_1().h_full().child(
|
||||||
div().flex().flex_1().child(self.center.render(
|
div().flex().flex_1().child(self.center.render(
|
||||||
project,
|
&self.project,
|
||||||
follower_states,
|
&self.follower_states,
|
||||||
active_call,
|
self.active_call(),
|
||||||
active_pane,
|
&self.active_pane,
|
||||||
zoomed,
|
self.zoomed.as_ref(),
|
||||||
app_state,
|
&self.app_state,
|
||||||
cx,
|
cx,
|
||||||
)),
|
)),
|
||||||
), // .children(
|
), // .children(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue