| @@ -10,7 +10,7 @@ use gpui::{ · 9 unmodified lines |
| 10 | actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyWeakView, AppContext, | 10 | actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyWeakView, AppContext, |
| 11 | AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, Focusable, | 11 | AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, Focusable, |
| 12 | FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, | 12 | FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, |
| 13 | Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, | 13 | ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, |
| 14 | }; | 14 | }; |
| 15 | use parking_lot::Mutex; | 15 | use parking_lot::Mutex; |
| 16 | use project::{Project, ProjectEntryId, ProjectPath}; | 16 | use project::{Project, ProjectEntryId, ProjectPath}; |
| @@ -25,13 +25,14 @@ use std::{ · 8 unmodified lines |
| 25 | Arc, | 25 | Arc, |
| 26 | }, | 26 | }, |
| 27 | }; | 27 | }; |
| | 28 | use theme::ThemeSettings; |
| 28 | | 29 | |
| 29 | use ui::{ | 30 | use ui::{ |
| 30 | h_stack, prelude::*, right_click_menu, ButtonSize, Color, Icon, IconButton, IconSize, | 31 | h_stack, prelude::*, right_click_menu, ButtonSize, Color, Icon, IconButton, IconSize, |
| 31 | Indicator, Label, Tab, TabBar, TabPosition, Tooltip, | 32 | Indicator, Label, Tab, TabBar, TabPosition, Tooltip, |
| 32 | }; | 33 | }; |
| 33 | use ui::{v_stack, ContextMenu}; | 34 | use ui::{v_stack, ContextMenu}; |
| 34 | use util::{maybe, truncate_and_remove_front}; | 35 | use util::{maybe, truncate_and_remove_front, ResultExt}; |
| 35 | | 36 | |
| 36 | #[derive(PartialEq, Clone, Copy, Deserialize, Debug)] | 37 | #[derive(PartialEq, Clone, Copy, Deserialize, Debug)] |
| 37 | #[serde(rename_all = "camelCase")] | 38 | #[serde(rename_all = "camelCase")] |
| @@ -176,10 +177,8 @@ pub struct Pane { · 138 unmodified lines |
| 176 | was_focused: bool, | 177 | was_focused: bool, |
| 177 | active_item_index: usize, | 178 | active_item_index: usize, |
| 178 | last_focused_view_by_item: HashMap<EntityId, FocusHandle>, | 179 | last_focused_view_by_item: HashMap<EntityId, FocusHandle>, |
| 179 | autoscroll: bool, | | |
| 180 | nav_history: NavHistory, | 180 | nav_history: NavHistory, |
| 181 | toolbar: View<Toolbar>, | 181 | toolbar: View<Toolbar>, |
| 182 | tab_bar_focus_handle: FocusHandle, | | |
| 183 | new_item_menu: Option<View<ContextMenu>>, | 182 | new_item_menu: Option<View<ContextMenu>>, |
| 184 | split_item_menu: Option<View<ContextMenu>>, | 183 | split_item_menu: Option<View<ContextMenu>>, |
| 185 | // tab_context_menu: ViewHandle<ContextMenu>, | 184 | // tab_context_menu: ViewHandle<ContextMenu>, |
| @@ -189,6 +188,7 @@ pub struct Pane { · 3 unmodified lines |
| 189 | can_split: bool, | 188 | can_split: bool, |
| 190 | // render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>, | 189 | // render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>, |
| 191 | subscriptions: Vec<Subscription>, | 190 | subscriptions: Vec<Subscription>, |
| | 191 | tab_bar_scroll_handle: ScrollHandle, |
| 192 | } | 192 | } |
| 193 | | 193 | |
| 194 | pub struct ItemNavHistory { | 194 | pub struct ItemNavHistory { |
| @@ -231,6 +231,14 @@ pub struct NavigationEntry { · 36 unmodified lines |
| 231 | pub timestamp: usize, | 231 | pub timestamp: usize, |
| 232 | } | 232 | } |
| 233 | | 233 | |
| | 234 | struct DraggedTab { |
| | 235 | pub pane: View<Pane>, |
| | 236 | pub ix: usize, |
| | 237 | pub item_id: EntityId, |
| | 238 | pub detail: usize, |
| | 239 | pub is_active: bool, |
| | 240 | } |
| | 241 | |
| 234 | // pub struct DraggedItem { | 242 | // pub struct DraggedItem { |
| 235 | // pub handle: Box<dyn ItemHandle>, | 243 | // pub handle: Box<dyn ItemHandle>, |
| 236 | // pub pane: WeakView<Pane>, | 244 | // pub pane: WeakView<Pane>, |
| @@ -344,7 +352,6 @@ impl Pane { · 107 unmodified lines |
| 344 | zoomed: false, | 352 | zoomed: false, |
| 345 | active_item_index: 0, | 353 | active_item_index: 0, |
| 346 | last_focused_view_by_item: Default::default(), | 354 | last_focused_view_by_item: Default::default(), |
| 347 | autoscroll: false, | | |
| 348 | nav_history: NavHistory(Arc::new(Mutex::new(NavHistoryState { | 355 | nav_history: NavHistory(Arc::new(Mutex::new(NavHistoryState { |
| 349 | mode: NavigationMode::Normal, | 356 | mode: NavigationMode::Normal, |
| 350 | backward_stack: Default::default(), | 357 | backward_stack: Default::default(), |
| @@ -355,9 +362,9 @@ impl Pane { · 4 unmodified lines |
| 355 | next_timestamp, | 362 | next_timestamp, |
| 356 | }))), | 363 | }))), |
| 357 | toolbar: cx.build_view(|_| Toolbar::new()), | 364 | toolbar: cx.build_view(|_| Toolbar::new()), |
| 358 | tab_bar_focus_handle: cx.focus_handle(), | | |
| 359 | new_item_menu: None, | 365 | new_item_menu: None, |
| 360 | split_item_menu: None, | 366 | split_item_menu: None, |
| | 367 | tab_bar_scroll_handle: ScrollHandle::new(), |
| 361 | // tab_bar_context_menu: TabBarContextMenu { | 368 | // tab_bar_context_menu: TabBarContextMenu { |
| 362 | // kind: TabBarContextMenuKind::New, | 369 | // kind: TabBarContextMenuKind::New, |
| 363 | // handle: context_menu, | 370 | // handle: context_menu, |
| @@ -460,8 +467,8 @@ impl Pane { · 96 unmodified lines |
| 460 | } | 467 | } |
| 461 | | 468 | |
| 462 | active_item.focus_handle(cx).focus(cx); | 469 | active_item.focus_handle(cx).focus(cx); |
| 463 | } else if !self.tab_bar_focus_handle.contains_focused(cx) { | 470 | } else if let Some(focused) = cx.focused() { |
| 464 | if let Some(focused) = cx.focused() { | 471 | if !self.context_menu_focused(cx) { |
| 465 | self.last_focused_view_by_item | 472 | self.last_focused_view_by_item |
| 466 | .insert(active_item.item_id(), focused); | 473 | .insert(active_item.item_id(), focused); |
| 467 | } | 474 | } |
| @@ -469,6 +476,13 @@ impl Pane { · 1 unmodified line |
| 469 | } | 476 | } |
| 470 | } | 477 | } |
| 471 | | 478 | |
| | 479 | fn context_menu_focused(&self, cx: &mut ViewContext<Self>) -> bool { |
| | 480 | self.new_item_menu |
| | 481 | .as_ref() |
| | 482 | .or(self.split_item_menu.as_ref()) |
| | 483 | .map_or(false, |menu| menu.focus_handle(cx).is_focused(cx)) |
| | 484 | } |
| | 485 | |
| 472 | fn focus_out(&mut self, cx: &mut ViewContext<Self>) { | 486 | fn focus_out(&mut self, cx: &mut ViewContext<Self>) { |
| 473 | self.was_focused = false; | 487 | self.was_focused = false; |
| 474 | self.toolbar.update(cx, |toolbar, cx| { | 488 | self.toolbar.update(cx, |toolbar, cx| { |
| @@ -785,7 +799,7 @@ impl Pane { · 310 unmodified lines |
| 785 | self.focus_active_item(cx); | 799 | self.focus_active_item(cx); |
| 786 | } | 800 | } |
| 787 | | 801 | |
| 788 | self.autoscroll = true; | 802 | self.tab_bar_scroll_handle.scroll_to_item(index); |
| 789 | cx.notify(); | 803 | cx.notify(); |
| 790 | } | 804 | } |
| 791 | } | 805 | } |
| @@ -1478,8 +1492,7 @@ impl Pane { · 686 unmodified lines |
| 1478 | Some(Indicator::dot().color(indicator_color)) | 1492 | Some(Indicator::dot().color(indicator_color)) |
| 1479 | }); | 1493 | }); |
| 1480 | | 1494 | |
| 1481 | let id = item.item_id(); | 1495 | let item_id = item.item_id(); |
| 1482 | | | |
| 1483 | let is_first_item = ix == 0; | 1496 | let is_first_item = ix == 0; |
| 1484 | let is_last_item = ix == self.items.len() - 1; | 1497 | let is_last_item = ix == self.items.len() - 1; |
| 1485 | let position_relative_to_active_item = ix.cmp(&self.active_item_index); | 1498 | let position_relative_to_active_item = ix.cmp(&self.active_item_index); |
| @@ -1501,11 +1514,24 @@ impl Pane { · 15 unmodified lines |
| 1501 | .on_click(cx.listener(move |pane: &mut Self, event, cx| { | 1514 | .on_click(cx.listener(move |pane: &mut Self, event, cx| { |
| 1502 | pane.activate_item(ix, true, true, cx) | 1515 | pane.activate_item(ix, true, true, cx) |
| 1503 | })) | 1516 | })) |
| 1504 | // .on_drag(move |pane, cx| pane.render_tab(ix, item.boxed_clone(), detail, cx)) | 1517 | .on_drag({ |
| 1505 | // .drag_over::<DraggedTab>(|d| d.bg(cx.theme().colors().element_drop_target)) | 1518 | let pane = cx.view().clone(); |
| 1506 | // .on_drop(|_view, state: View<DraggedTab>, cx| { | 1519 | move |cx| { |
| 1507 | // eprintln!("{:?}", state.read(cx)); | 1520 | cx.build_view(|cx| DraggedTab { |
| 1508 | // }) | 1521 | pane: pane.clone(), |
| | 1522 | detail, |
| | 1523 | item_id, |
| | 1524 | is_active, |
| | 1525 | ix, |
| | 1526 | }) |
| | 1527 | } |
| | 1528 | }) |
| | 1529 | .drag_over::<DraggedTab>(|tab| tab.bg(cx.theme().colors().tab_active_background)) |
| | 1530 | .on_drop( |
| | 1531 | cx.listener(move |this, dragged_tab: &View<DraggedTab>, cx| { |
| | 1532 | this.handle_tab_drop(dragged_tab, ix, cx) |
| | 1533 | }), |
| | 1534 | ) |
| 1509 | .when_some(item.tab_tooltip_text(cx), |tab, text| { | 1535 | .when_some(item.tab_tooltip_text(cx), |tab, text| { |
| 1510 | tab.tooltip(move |cx| Tooltip::text(text.clone(), cx)) | 1536 | tab.tooltip(move |cx| Tooltip::text(text.clone(), cx)) |
| 1511 | }) | 1537 | }) |
| @@ -1516,7 +1542,7 @@ impl Pane { · 4 unmodified lines |
| 1516 | .size(ButtonSize::None) | 1542 | .size(ButtonSize::None) |
| 1517 | .icon_size(IconSize::XSmall) | 1543 | .icon_size(IconSize::XSmall) |
| 1518 | .on_click(cx.listener(move |pane, _, cx| { | 1544 | .on_click(cx.listener(move |pane, _, cx| { |
| 1519 | pane.close_item_by_id(id, SaveIntent::Close, cx) | 1545 | pane.close_item_by_id(item_id, SaveIntent::Close, cx) |
| 1520 | .detach_and_log_err(cx); | 1546 | .detach_and_log_err(cx); |
| 1521 | })), | 1547 | })), |
| 1522 | ) | 1548 | ) |
| @@ -1562,7 +1588,8 @@ impl Pane { · 39 unmodified lines |
| 1562 | } | 1588 | } |
| 1563 | | 1589 | |
| 1564 | fn render_tab_bar(&mut self, cx: &mut ViewContext<'_, Pane>) -> impl IntoElement { | 1590 | fn render_tab_bar(&mut self, cx: &mut ViewContext<'_, Pane>) -> impl IntoElement { |
| 1565 | TabBar::new("tab_bar", self.tab_bar_focus_handle.clone()) | 1591 | TabBar::new("tab_bar") |
| | 1592 | .track_scroll(self.tab_bar_scroll_handle.clone()) |
| 1566 | .start_child( | 1593 | .start_child( |
| 1567 | IconButton::new("navigate_backward", Icon::ArrowLeft) | 1594 | IconButton::new("navigate_backward", Icon::ArrowLeft) |
| 1568 | .icon_size(IconSize::Small) | 1595 | .icon_size(IconSize::Small) |
| @@ -1635,6 +1662,19 @@ impl Pane { · 66 unmodified lines |
| 1635 | .zip(self.tab_details(cx)) | 1662 | .zip(self.tab_details(cx)) |
| 1636 | .map(|((ix, item), detail)| self.render_tab(ix, item, detail, cx)), | 1663 | .map(|((ix, item), detail)| self.render_tab(ix, item, detail, cx)), |
| 1637 | ) | 1664 | ) |
| | 1665 | .child( |
| | 1666 | div() |
| | 1667 | .h_full() |
| | 1668 | .flex_grow() |
| | 1669 | .drag_over::<DraggedTab>(|bar| { |
| | 1670 | bar.bg(cx.theme().colors().tab_active_background) |
| | 1671 | }) |
| | 1672 | .on_drop( |
| | 1673 | cx.listener(move |this, dragged_tab: &View<DraggedTab>, cx| { |
| | 1674 | this.handle_tab_drop(dragged_tab, this.items.len(), cx) |
| | 1675 | }), |
| | 1676 | ), |
| | 1677 | ) |
| 1638 | } | 1678 | } |
| 1639 | | 1679 | |
| 1640 | fn render_menu_overlay(menu: &View<ContextMenu>) -> Div { | 1680 | fn render_menu_overlay(menu: &View<ContextMenu>) -> Div { |
| @@ -1647,161 +1687,6 @@ impl Pane { · 6 unmodified lines |
| 1647 | .child(overlay().anchor(AnchorCorner::TopRight).child(menu.clone())) | 1687 | .child(overlay().anchor(AnchorCorner::TopRight).child(menu.clone())) |
| 1648 | } | 1688 | } |
| 1649 | | 1689 | |
| 1650 | // fn render_tabs(&mut self, cx: &mut ViewContext<Self>) -> impl Element<Self> { | | |
| 1651 | // let theme = theme::current(cx).clone(); | | |
| 1652 | | | |
| 1653 | // let pane = cx.handle().downgrade(); | | |
| 1654 | // let autoscroll = if mem::take(&mut self.autoscroll) { | | |
| 1655 | // Some(self.active_item_index) | | |
| 1656 | // } else { | | |
| 1657 | // None | | |
| 1658 | // }; | | |
| 1659 | | | |
| 1660 | // let pane_active = self.has_focus; | | |
| 1661 | | | |
| 1662 | // enum Tabs {} | | |
| 1663 | // let mut row = Flex::row().scrollable::<Tabs>(1, autoscroll, cx); | | |
| 1664 | // for (ix, (item, detail)) in self | | |
| 1665 | // .items | | |
| 1666 | // .iter() | | |
| 1667 | // .cloned() | | |
| 1668 | // .zip(self.tab_details(cx)) | | |
| 1669 | // .enumerate() | | |
| 1670 | // { | | |
| 1671 | // let git_status = item | | |
| 1672 | // .project_path(cx) | | |
| 1673 | // .and_then(|path| self.project.read(cx).entry_for_path(&path, cx)) | | |
| 1674 | // .and_then(|entry| entry.git_status()); | | |
| 1675 | | | |
| 1676 | // let detail = if detail == 0 { None } else { Some(detail) }; | | |
| 1677 | // let tab_active = ix == self.active_item_index; | | |
| 1678 | | | |
| 1679 | // row.add_child({ | | |
| 1680 | // enum TabDragReceiver {} | | |
| 1681 | // let mut receiver = | | |
| 1682 | // dragged_item_receiver::<TabDragReceiver, _, _>(self, ix, ix, true, None, cx, { | | |
| 1683 | // let item = item.clone(); | | |
| 1684 | // let pane = pane.clone(); | | |
| 1685 | // let detail = detail.clone(); | | |
| 1686 | | | |
| 1687 | // let theme = theme::current(cx).clone(); | | |
| 1688 | // let mut tooltip_theme = theme.tooltip.clone(); | | |
| 1689 | // tooltip_theme.max_text_width = None; | | |
| 1690 | // let tab_tooltip_text = | | |
| 1691 | // item.tab_tooltip_text(cx).map(|text| text.into_owned()); | | |
| 1692 | | | |
| 1693 | // let mut tab_style = theme | | |
| 1694 | // .workspace | | |
| 1695 | // .tab_bar | | |
| 1696 | // .tab_style(pane_active, tab_active) | | |
| 1697 | // .clone(); | | |
| 1698 | // let should_show_status = settings::get::<ItemSettings>(cx).git_status; | | |
| 1699 | // if should_show_status && git_status != None { | | |
| 1700 | // tab_style.label.text.color = match git_status.unwrap() { | | |
| 1701 | // GitFileStatus::Added => tab_style.git.inserted, | | |
| 1702 | // GitFileStatus::Modified => tab_style.git.modified, | | |
| 1703 | // GitFileStatus::Conflict => tab_style.git.conflict, | | |
| 1704 | // }; | | |
| 1705 | // } | | |
| 1706 | | | |
| 1707 | // move |mouse_state, cx| { | | |
| 1708 | // let hovered = mouse_state.hovered(); | | |
| 1709 | | | |
| 1710 | // enum Tab {} | | |
| 1711 | // let mouse_event_handler = | | |
| 1712 | // MouseEventHandler::new::<Tab, _>(ix, cx, |_, cx| { | | |
| 1713 | // Self::render_tab( | | |
| 1714 | // &item, | | |
| 1715 | // pane.clone(), | | |
| 1716 | // ix == 0, | | |
| 1717 | // detail, | | |
| 1718 | // hovered, | | |
| 1719 | // &tab_style, | | |
| 1720 | // cx, | | |
| 1721 | // ) | | |
| 1722 | // }) | | |
| 1723 | // .on_down(MouseButton::Left, move |_, this, cx| { | | |
| 1724 | // this.activate_item(ix, true, true, cx); | | |
| 1725 | // }) | | |
| 1726 | // .on_click(MouseButton::Middle, { | | |
| 1727 | // let item_id = item.id(); | | |
| 1728 | // move |_, pane, cx| { | | |
| 1729 | // pane.close_item_by_id(item_id, SaveIntent::Close, cx) | | |
| 1730 | // .detach_and_log_err(cx); | | |
| 1731 | // } | | |
| 1732 | // }) | | |
| 1733 | // .on_down( | | |
| 1734 | // MouseButton::Right, | | |
| 1735 | // move |event, pane, cx| { | | |
| 1736 | // pane.deploy_tab_context_menu(event.position, item.id(), cx); | | |
| 1737 | // }, | | |
| 1738 | // ); | | |
| 1739 | | | |
| 1740 | // if let Some(tab_tooltip_text) = tab_tooltip_text { | | |
| 1741 | // mouse_event_handler | | |
| 1742 | // .with_tooltip::<Self>( | | |
| 1743 | // ix, | | |
| 1744 | // tab_tooltip_text, | | |
| 1745 | // None, | | |
| 1746 | // tooltip_theme, | | |
| 1747 | // cx, | | |
| 1748 | // ) | | |
| 1749 | // .into_any() | | |
| 1750 | // } else { | | |
| 1751 | // mouse_event_handler.into_any() | | |
| 1752 | // } | | |
| 1753 | // } | | |
| 1754 | // }); | | |
| 1755 | | | |
| 1756 | // if !pane_active || !tab_active { | | |
| 1757 | // receiver = receiver.with_cursor_style(CursorStyle::PointingHand); | | |
| 1758 | // } | | |
| 1759 | | | |
| 1760 | // receiver.as_draggable( | | |
| 1761 | // DraggedItem { | | |
| 1762 | // handle: item, | | |
| 1763 | // pane: pane.clone(), | | |
| 1764 | // }, | | |
| 1765 | // { | | |
| 1766 | // let theme = theme::current(cx).clone(); | | |
| 1767 | | | |
| 1768 | // let detail = detail.clone(); | | |
| 1769 | // move |_, dragged_item: &DraggedItem, cx: &mut ViewContext<Workspace>| { | | |
| 1770 | // let tab_style = &theme.workspace.tab_bar.dragged_tab; | | |
| 1771 | // Self::render_dragged_tab( | | |
| 1772 | // &dragged_item.handle, | | |
| 1773 | // dragged_item.pane.clone(), | | |
| 1774 | // false, | | |
| 1775 | // detail, | | |
| 1776 | // false, | | |
| 1777 | // &tab_style, | | |
| 1778 | // cx, | | |
| 1779 | // ) | | |
| 1780 | // } | | |
| 1781 | // }, | | |
| 1782 | // ) | | |
| 1783 | // }) | | |
| 1784 | // } | | |
| 1785 | | | |
| 1786 | // // Use the inactive tab style along with the current pane's active status to decide how to render | | |
| 1787 | // // the filler | | |
| 1788 | // let filler_index = self.items.len(); | | |
| 1789 | // let filler_style = theme.workspace.tab_bar.tab_style(pane_active, false); | | |
| 1790 | // enum Filler {} | | |
| 1791 | // row.add_child( | | |
| 1792 | // dragged_item_receiver::<Filler, _, _>(self, 0, filler_index, true, None, cx, |_, _| { | | |
| 1793 | // Empty::new() | | |
| 1794 | // .contained() | | |
| 1795 | // .with_style(filler_style.container) | | |
| 1796 | // .with_border(filler_style.container.border) | | |
| 1797 | // }) | | |
| 1798 | // .flex(1., true) | | |
| 1799 | // .into_any_named("filler"), | | |
| 1800 | // ); | | |
| 1801 | | | |
| 1802 | // row | | |
| 1803 | // } | | |
| 1804 | | | |
| 1805 | fn tab_details(&self, cx: &AppContext) -> Vec<usize> { | 1690 | fn tab_details(&self, cx: &AppContext) -> Vec<usize> { |
| 1806 | let mut tab_details = self.items.iter().map(|_| 0).collect::<Vec<_>>(); | 1691 | let mut tab_details = self.items.iter().map(|_| 0).collect::<Vec<_>>(); |
| 1807 | | 1692 | |
| @@ -1839,192 +1724,6 @@ impl Pane { · 31 unmodified lines |
| 1839 | tab_details | 1724 | tab_details |
| 1840 | } | 1725 | } |
| 1841 | | 1726 | |
| 1842 | // fn render_tab( | | |
| 1843 | // item: &Box<dyn ItemHandle>, | | |
| 1844 | // pane: WeakView<Pane>, | | |
| 1845 | // first: bool, | | |
| 1846 | // detail: Option<usize>, | | |
| 1847 | // hovered: bool, | | |
| 1848 | // tab_style: &theme::Tab, | | |
| 1849 | // cx: &mut ViewContext<Self>, | | |
| 1850 | // ) -> AnyElement<Self> { | | |
| 1851 | // let title = item.tab_content(detail, &tab_style, cx); | | |
| 1852 | // Self::render_tab_with_title(title, item, pane, first, hovered, tab_style, cx) | | |
| 1853 | // } | | |
| 1854 | | | |
| 1855 | // fn render_dragged_tab( | | |
| 1856 | // item: &Box<dyn ItemHandle>, | | |
| 1857 | // pane: WeakView<Pane>, | | |
| 1858 | // first: bool, | | |
| 1859 | // detail: Option<usize>, | | |
| 1860 | // hovered: bool, | | |
| 1861 | // tab_style: &theme::Tab, | | |
| 1862 | // cx: &mut ViewContext<Workspace>, | | |
| 1863 | // ) -> AnyElement<Workspace> { | | |
| 1864 | // let title = item.dragged_tab_content(detail, &tab_style, cx); | | |
| 1865 | // Self::render_tab_with_title(title, item, pane, first, hovered, tab_style, cx) | | |
| 1866 | // } | | |
| 1867 | | | |
| 1868 | // fn render_tab_with_title<T: View>( | | |
| 1869 | // title: AnyElement<T>, | | |
| 1870 | // item: &Box<dyn ItemHandle>, | | |
| 1871 | // pane: WeakView<Pane>, | | |
| 1872 | // first: bool, | | |
| 1873 | // hovered: bool, | | |
| 1874 | // tab_style: &theme::Tab, | | |
| 1875 | // cx: &mut ViewContext<T>, | | |
| 1876 | // ) -> AnyElement<T> { | | |
| 1877 | // let mut container = tab_style.container.clone(); | | |
| 1878 | // if first { | | |
| 1879 | // container.border.left = false; | | |
| 1880 | // } | | |
| 1881 | | | |
| 1882 | // let buffer_jewel_element = { | | |
| 1883 | // let diameter = 7.0; | | |
| 1884 | // let icon_color = if item.has_conflict(cx) { | | |
| 1885 | // Some(tab_style.icon_conflict) | | |
| 1886 | // } else if item.is_dirty(cx) { | | |
| 1887 | // Some(tab_style.icon_dirty) | | |
| 1888 | // } else { | | |
| 1889 | // None | | |
| 1890 | // }; | | |
| 1891 | | | |
| 1892 | // Canvas::new(move |bounds, _, _, cx| { | | |
| 1893 | // if let Some(color) = icon_color { | | |
| 1894 | // let square = RectF::new(bounds.origin(), vec2f(diameter, diameter)); | | |
| 1895 | // cx.scene().push_quad(Quad { | | |
| 1896 | // bounds: square, | | |
| 1897 | // background: Some(color), | | |
| 1898 | // border: Default::default(), | | |
| 1899 | // corner_radii: (diameter / 2.).into(), | | |
| 1900 | // }); | | |
| 1901 | // } | | |
| 1902 | // }) | | |
| 1903 | // .constrained() | | |
| 1904 | // .with_width(diameter) | | |
| 1905 | // .with_height(diameter) | | |
| 1906 | // .aligned() | | |
| 1907 | // }; | | |
| 1908 | | | |
| 1909 | // let title_element = title.aligned().contained().with_style(ContainerStyle { | | |
| 1910 | // margin: Margin { | | |
| 1911 | // left: tab_style.spacing, | | |
| 1912 | // right: tab_style.spacing, | | |
| 1913 | // ..Default::default() | | |
| 1914 | // }, | | |
| 1915 | // ..Default::default() | | |
| 1916 | // }); | | |
| 1917 | | | |
| 1918 | // let close_element = if hovered { | | |
| 1919 | // let item_id = item.id(); | | |
| 1920 | // enum TabCloseButton {} | | |
| 1921 | // let icon = Svg::new("icons/x.svg"); | | |
| 1922 | // MouseEventHandler::new::<TabCloseButton, _>(item_id, cx, |mouse_state, _| { | | |
| 1923 | // if mouse_state.hovered() { | | |
| 1924 | // icon.with_color(tab_style.icon_close_active) | | |
| 1925 | // } else { | | |
| 1926 | // icon.with_color(tab_style.icon_close) | | |
| 1927 | // } | | |
| 1928 | // }) | | |
| 1929 | // .with_padding(Padding::uniform(4.)) | | |
| 1930 | // .with_cursor_style(CursorStyle::PointingHand) | | |
| 1931 | // .on_click(MouseButton::Left, { | | |
| 1932 | // let pane = pane.clone(); | | |
| 1933 | // move |_, _, cx| { | | |
| 1934 | // let pane = pane.clone(); | | |
| 1935 | // cx.window_context().defer(move |cx| { | | |
| 1936 | // if let Some(pane) = pane.upgrade(cx) { | | |
| 1937 | // pane.update(cx, |pane, cx| { | | |
| 1938 | // pane.close_item_by_id(item_id, SaveIntent::Close, cx) | | |
| 1939 | // .detach_and_log_err(cx); | | |
| 1940 | // }); | | |
| 1941 | // } | | |
| 1942 | // }); | | |
| 1943 | // } | | |
| 1944 | // }) | | |
| 1945 | // .into_any_named("close-tab-icon") | | |
| 1946 | // .constrained() | | |
| 1947 | // } else { | | |
| 1948 | // Empty::new().constrained() | | |
| 1949 | // } | | |
| 1950 | // .with_width(tab_style.close_icon_width) | | |
| 1951 | // .aligned(); | | |
| 1952 | | | |
| 1953 | // let close_right = settings::get::<ItemSettings>(cx).close_position.right(); | | |
| 1954 | | | |
| 1955 | // if close_right { | | |
| 1956 | // Flex::row() | | |
| 1957 | // .with_child(buffer_jewel_element) | | |
| 1958 | // .with_child(title_element) | | |
| 1959 | // .with_child(close_element) | | |
| 1960 | // } else { | | |
| 1961 | // Flex::row() | | |
| 1962 | // .with_child(close_element) | | |
| 1963 | // .with_child(title_element) | | |
| 1964 | // .with_child(buffer_jewel_element) | | |
| 1965 | // } | | |
| 1966 | // .contained() | | |
| 1967 | // .with_style(container) | | |
| 1968 | // .constrained() | | |
| 1969 | // .with_height(tab_style.height) | | |
| 1970 | // .into_any() | | |
| 1971 | // } | | |
| 1972 | | | |
| 1973 | // pub fn render_tab_bar_button< | | |
| 1974 | // F1: 'static + Fn(&mut Pane, &mut EventContext<Pane>), | | |
| 1975 | // F2: 'static + Fn(&mut Pane, &mut EventContext<Pane>), | | |
| 1976 | // >( | | |
| 1977 | // index: usize, | | |
| 1978 | // icon: &'static str, | | |
| 1979 | // is_active: bool, | | |
| 1980 | // tooltip: Option<(&'static str, Option<Box<dyn Action>>)>, | | |
| 1981 | // cx: &mut ViewContext<Pane>, | | |
| 1982 | // on_click: F1, | | |
| 1983 | // on_down: F2, | | |
| 1984 | // context_menu: Option<ViewHandle<ContextMenu>>, | | |
| 1985 | // ) -> AnyElement<Pane> { | | |
| 1986 | // enum TabBarButton {} | | |
| 1987 | | | |
| 1988 | // let mut button = MouseEventHandler::new::<TabBarButton, _>(index, cx, |mouse_state, cx| { | | |
| 1989 | // let theme = &settings2::get::<ThemeSettings>(cx).theme.workspace.tab_bar; | | |
| 1990 | // let style = theme.pane_button.in_state(is_active).style_for(mouse_state); | | |
| 1991 | // Svg::new(icon) | | |
| 1992 | // .with_color(style.color) | | |
| 1993 | // .constrained() | | |
| 1994 | // .with_width(style.icon_width) | | |
| 1995 | // .aligned() | | |
| 1996 | // .constrained() | | |
| 1997 | // .with_width(style.button_width) | | |
| 1998 | // .with_height(style.button_width) | | |
| 1999 | // }) | | |
| 2000 | // .with_cursor_style(CursorStyle::PointingHand) | | |
| 2001 | // .on_down(MouseButton::Left, move |_, pane, cx| on_down(pane, cx)) | | |
| 2002 | // .on_click(MouseButton::Left, move |_, pane, cx| on_click(pane, cx)) | | |
| 2003 | // .into_any(); | | |
| 2004 | // if let Some((tooltip, action)) = tooltip { | | |
| 2005 | // let tooltip_style = settings::get::<ThemeSettings>(cx).theme.tooltip.clone(); | | |
| 2006 | // button = button | | |
| 2007 | // .with_tooltip::<TabBarButton>(index, tooltip, action, tooltip_style, cx) | | |
| 2008 | // .into_any(); | | |
| 2009 | // } | | |
| 2010 | | | |
| 2011 | // Stack::new() | | |
| 2012 | // .with_child(button) | | |
| 2013 | // .with_children( | | |
| 2014 | // context_menu.map(|menu| ChildView::new(&menu, cx).aligned().bottom().right()), | | |
| 2015 | // ) | | |
| 2016 | // .flex(1., false) | | |
| 2017 | // .into_any_named("tab bar button") | | |
| 2018 | // } | | |
| 2019 | | | |
| 2020 | // fn render_blank_pane(&self, theme: &Theme, _cx: &mut ViewContext<Self>) -> AnyElement<Self> { | | |
| 2021 | // let background = theme.workspace.background; | | |
| 2022 | // Empty::new() | | |
| 2023 | // .contained() | | |
| 2024 | // .with_background_color(background) | | |
| 2025 | // .into_any() | | |
| 2026 | // } | | |
| 2027 | | | |
| 2028 | pub fn set_zoomed(&mut self, zoomed: bool, cx: &mut ViewContext<Self>) { | 1727 | pub fn set_zoomed(&mut self, zoomed: bool, cx: &mut ViewContext<Self>) { |
| 2029 | self.zoomed = zoomed; | 1728 | self.zoomed = zoomed; |
| 2030 | cx.notify(); | 1729 | cx.notify(); |
| @@ -2033,6 +1732,25 @@ impl Pane { · 2 unmodified lines |
| 2033 | pub fn is_zoomed(&self) -> bool { | 1732 | pub fn is_zoomed(&self) -> bool { |
| 2034 | self.zoomed | 1733 | self.zoomed |
| 2035 | } | 1734 | } |
| | 1735 | |
| | 1736 | fn handle_tab_drop( |
| | 1737 | &mut self, |
| | 1738 | dragged_tab: &View<DraggedTab>, |
| | 1739 | ix: usize, |
| | 1740 | cx: &mut ViewContext<'_, Pane>, |
| | 1741 | ) { |
| | 1742 | let dragged_tab = dragged_tab.read(cx); |
| | 1743 | let item_id = dragged_tab.item_id; |
| | 1744 | let from_pane = dragged_tab.pane.clone(); |
| | 1745 | let to_pane = cx.view().clone(); |
| | 1746 | self.workspace |
| | 1747 | .update(cx, |workspace, cx| { |
| | 1748 | cx.defer(move |workspace, cx| { |
| | 1749 | workspace.move_item(from_pane, to_pane, item_id, ix, cx); |
| | 1750 | }); |
| | 1751 | }) |
| | 1752 | .log_err(); |
| | 1753 | } |
| 2036 | } | 1754 | } |
| 2037 | | 1755 | |
| 2038 | impl FocusableView for Pane { | 1756 | impl FocusableView for Pane { |
| @@ -2134,148 +1852,6 @@ impl Render for Pane { · 95 unmodified lines |
| 2134 | .justify_center() | 1852 | .justify_center() |
| 2135 | .child(Label::new("Open a file or project to get started.").color(Color::Muted)) | 1853 | .child(Label::new("Open a file or project to get started.").color(Color::Muted)) |
| 2136 | }) | 1854 | }) |
| 2137 | // enum MouseNavigationHandler {} | | |
| 2138 | // MouseEventHandler::new::<MouseNavigationHandler, _>(0, cx, |_, cx| { | | |
| 2139 | // let active_item_index = self.active_item_index; | | |
| 2140 | // if let Some(active_item) = self.active_item() { | | |
| 2141 | // Flex::column() | | |
| 2142 | // .with_child({ | | |
| 2143 | // let theme = theme::current(cx).clone(); | | |
| 2144 | // let mut stack = Stack::new(); | | |
| 2145 | // enum TabBarEventHandler {} | | |
| 2146 | // stack.add_child( | | |
| 2147 | // MouseEventHandler::new::<TabBarEventHandler, _>(0, cx, |_, _| { | | |
| 2148 | // Empty::new() | | |
| 2149 | // .contained() | | |
| 2150 | // .with_style(theme.workspace.tab_bar.container) | | |
| 2151 | // }) | | |
| 2152 | // .on_down( | | |
| 2153 | // MouseButton::Left, | | |
| 2154 | // move |_, this, cx| { | | |
| 2155 | // this.activate_item(active_item_index, true, true, cx); | | |
| 2156 | // }, | | |
| 2157 | // ), | | |
| 2158 | // ); | | |
| 2159 | // let tooltip_style = theme.tooltip.clone(); | | |
| 2160 | // let tab_bar_theme = theme.workspace.tab_bar.clone(); | | |
| 2161 | // let nav_button_height = tab_bar_theme.height; | | |
| 2162 | // let button_style = tab_bar_theme.nav_button; | | |
| 2163 | // let border_for_nav_buttons = tab_bar_theme | | |
| 2164 | // .tab_style(false, false) | | |
| 2165 | // .container | | |
| 2166 | // .border | | |
| 2167 | // .clone(); | | |
| 2168 | // let mut tab_row = Flex::row() | | |
| 2169 | // .with_child(nav_button( | | |
| 2170 | // "icons/arrow_left.svg", | | |
| 2171 | // button_style.clone(), | | |
| 2172 | // nav_button_height, | | |
| 2173 | // tooltip_style.clone(), | | |
| 2174 | // self.can_navigate_backward(), | | |
| 2175 | // { | | |
| 2176 | // move |pane, cx| { | | |
| 2177 | // if let Some(workspace) = pane.workspace.upgrade(cx) { | | |
| 2178 | // let pane = cx.weak_handle(); | | |
| 2179 | // cx.window_context().defer(move |cx| { | | |
| 2180 | // workspace.update(cx, |workspace, cx| { | | |
| 2181 | // workspace | | |
| 2182 | // .go_back(pane, cx) | | |
| 2183 | // .detach_and_log_err(cx) | | |
| 2184 | // }) | | |
| 2185 | // }) | | |
| 2186 | // } | | |
| 2187 | // } | | |
| 2188 | // }, | | |
| 2189 | // super::GoBack, | | |
| 2190 | // "Go Back", | | |
| 2191 | // cx, | | |
| 2192 | // )) | | |
| 2193 | // .with_child( | | |
| 2194 | // nav_button( | | |
| 2195 | // "icons/arrow_right.svg", | | |
| 2196 | // button_style.clone(), | | |
| 2197 | // nav_button_height, | | |
| 2198 | // tooltip_style, | | |
| 2199 | // self.can_navigate_forward(), | | |
| 2200 | // { | | |
| 2201 | // move |pane, cx| { | | |
| 2202 | // if let Some(workspace) = pane.workspace.upgrade(cx) { | | |
| 2203 | // let pane = cx.weak_handle(); | | |
| 2204 | // cx.window_context().defer(move |cx| { | | |
| 2205 | // workspace.update(cx, |workspace, cx| { | | |
| 2206 | // workspace | | |
| 2207 | // .go_forward(pane, cx) | | |
| 2208 | // .detach_and_log_err(cx) | | |
| 2209 | // }) | | |
| 2210 | // }) | | |
| 2211 | // } | | |
| 2212 | // } | | |
| 2213 | // }, | | |
| 2214 | // super::GoForward, | | |
| 2215 | // "Go Forward", | | |
| 2216 | // cx, | | |
| 2217 | // ) | | |
| 2218 | // .contained() | | |
| 2219 | // .with_border(border_for_nav_buttons), | | |
| 2220 | // ) | | |
| 2221 | // .with_child(self.render_tabs(cx).flex(1., true).into_any_named("tabs")); | | |
| 2222 | // if self.has_focus { | | |
| 2223 | // let render_tab_bar_buttons = self.render_tab_bar_buttons.clone(); | | |
| 2224 | // tab_row.add_child( | | |
| 2225 | // (render_tab_bar_buttons)(self, cx) | | |
| 2226 | // .contained() | | |
| 2227 | // .with_style(theme.workspace.tab_bar.pane_button_container) | | |
| 2228 | // .flex(1., false) | | |
| 2229 | // .into_any(), | | |
| 2230 | // ) | | |
| 2231 | // } | | |
| 2232 | // stack.add_child(tab_row); | | |
| 2233 | // stack | | |
| 2234 | // .constrained() | | |
| 2235 | // .with_height(theme.workspace.tab_bar.height) | | |
| 2236 | // .flex(1., false) | | |
| 2237 | // .into_any_named("tab bar") | | |
| 2238 | // }) | | |
| 2239 | // .with_child({ | | |
| 2240 | // enum PaneContentTabDropTarget {} | | |
| 2241 | // dragged_item_receiver::<PaneContentTabDropTarget, _, _>( | | |
| 2242 | // self, | | |
| 2243 | // 0, | | |
| 2244 | // self.active_item_index + 1, | | |
| 2245 | // !self.can_split, | | |
| 2246 | // if self.can_split { Some(100.) } else { None }, | | |
| 2247 | // cx, | | |
| 2248 | // { | | |
| 2249 | // let toolbar = self.toolbar.clone(); | | |
| 2250 | // let toolbar_hidden = toolbar.read(cx).hidden(); | | |
| 2251 | // move |_, cx| { | | |
| 2252 | // Flex::column() | | |
| 2253 | // .with_children( | | |
| 2254 | // (!toolbar_hidden) | | |
| 2255 | // .then(|| ChildView::new(&toolbar, cx).expanded()), | | |
| 2256 | // ) | | |
| 2257 | // .with_child( | | |
| 2258 | // ChildView::new(active_item.as_any(), cx).flex(1., true), | | |
| 2259 | // ) | | |
| 2260 | // } | | |
| 2261 | // }, | | |
| 2262 | // ) | | |
| 2263 | // .flex(1., true) | | |
| 2264 | // }) | | |
| 2265 | // .with_child(ChildView::new(&self.tab_context_menu, cx)) | | |
| 2266 | // .into_any() | | |
| 2267 | // } else { | | |
| 2268 | // enum EmptyPane {} | | |
| 2269 | // let theme = theme::current(cx).clone(); | | |
| 2270 | // dragged_item_receiver::<EmptyPane, _, _>(self, 0, 0, false, None, cx, |_, cx| { | | |
| 2271 | // self.render_blank_pane(&theme, cx) | | |
| 2272 | // }) | | |
| 2273 | // .on_down(MouseButton::Left, |_, _, cx| { | | |
| 2274 | // cx.focus_parent(); | | |
| 2275 | // }) | | |
| 2276 | // .into_any() | | |
| 2277 | // } | | |
| 2278 | // }) | | |
| 2279 | .on_mouse_down( | 1855 | .on_mouse_down( |
| 2280 | MouseButton::Navigate(NavigationDirection::Back), | 1856 | MouseButton::Navigate(NavigationDirection::Back), |
| 2281 | cx.listener(|pane, _, cx| { | 1857 | cx.listener(|pane, _, cx| { |
| @@ -2302,7 +1878,6 @@ impl Render for Pane { · 20 unmodified lines |
| 2302 | } | 1878 | } |
| 2303 | }), | 1879 | }), |
| 2304 | ) | 1880 | ) |
| 2305 | // .into_any_named("pane") | | |
| 2306 | } | 1881 | } |
| 2307 | | 1882 | |
| 2308 | // fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) { | 1883 | // fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) { |
| @@ -3131,15 +2706,17 @@ fn dirty_message_for(buffer_path: Option<ProjectPath>) -> String { · 822 unmodified lines |
| 3131 | // } | 2706 | // } |
| 3132 | // } | 2707 | // } |
| 3133 | | 2708 | |
| 3134 | #[derive(Clone, Debug)] | | |
| 3135 | struct DraggedTab { | | |
| 3136 | title: String, | | |
| 3137 | } | | |
| 3138 | | | |
| 3139 | impl Render for DraggedTab { | 2709 | impl Render for DraggedTab { |
| 3140 | type Element = Div; | 2710 | type Element = <Tab as RenderOnce>::Rendered; |
| 3141 | | 2711 | |
| 3142 | fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { | 2712 | fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { |
| 3143 | div().w_8().h_4().bg(gpui::red()) | 2713 | let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone(); |
| | 2714 | let item = &self.pane.read(cx).items[self.ix]; |
| | 2715 | let label = item.tab_content(Some(self.detail), false, cx); |
| | 2716 | Tab::new("") |
| | 2717 | .selected(self.is_active) |
| | 2718 | .child(label) |
| | 2719 | .render(cx) |
| | 2720 | .font(ui_font) |
| 3144 | } | 2721 | } |
| 3145 | } | 2722 | } |