@@ -29,9 +29,10 @@ use settings::Settings;
use stack_frame_list::StackFrameList;
use terminal_view::TerminalView;
use ui::{
- ActiveTheme, AnyElement, App, Context, ContextMenu, DropdownMenu, FluentBuilder,
- InteractiveElement, IntoElement, Label, LabelCommon as _, ParentElement, Render, SharedString,
- StatefulInteractiveElement, Styled, Tab, Window, div, h_flex, v_flex,
+ ActiveTheme, AnyElement, App, ButtonCommon as _, Clickable as _, Context, ContextMenu,
+ DropdownMenu, FluentBuilder, IconButton, IconName, IconSize, InteractiveElement, IntoElement,
+ Label, LabelCommon as _, ParentElement, Render, SharedString, StatefulInteractiveElement,
+ Styled, Tab, Tooltip, Window, div, h_flex, v_flex,
};
use util::ResultExt;
use variable_list::VariableList;
@@ -62,8 +63,16 @@ pub struct RunningState {
impl Render for RunningState {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let zoomed_pane = self
+ .panes
+ .panes()
+ .into_iter()
+ .find(|pane| pane.read(cx).is_zoomed());
+
let active = self.panes.panes().into_iter().next();
- let x = if let Some(active) = active {
+ let x = if let Some(ref zoomed_pane) = zoomed_pane {
+ zoomed_pane.update(cx, |pane, cx| pane.render(window, cx).into_any_element())
+ } else if let Some(active) = active {
self.panes
.render(
None,
@@ -257,109 +266,148 @@ pub(crate) fn new_debugger_pane(
window,
cx,
);
- pane.set_can_split(Some(Arc::new(move |pane, dragged_item, _window, cx| {
- if let Some(tab) = dragged_item.downcast_ref::<DraggedTab>() {
- let is_current_pane = tab.pane == cx.entity();
- let Some(can_drag_away) = weak_running
- .update(cx, |running_state, _| {
- let current_panes = running_state.panes.panes();
- !current_panes.contains(&&tab.pane)
- || current_panes.len() > 1
- || (!is_current_pane || pane.items_len() > 1)
- })
- .ok()
- else {
- return false;
- };
- if can_drag_away {
- let item = if is_current_pane {
- pane.item_for_index(tab.ix)
- } else {
- tab.pane.read(cx).item_for_index(tab.ix)
+ let focus_handle = pane.focus_handle(cx);
+ pane.set_can_split(Some(Arc::new({
+ let weak_running = weak_running.clone();
+ move |pane, dragged_item, _window, cx| {
+ if let Some(tab) = dragged_item.downcast_ref::<DraggedTab>() {
+ let is_current_pane = tab.pane == cx.entity();
+ let Some(can_drag_away) = weak_running
+ .update(cx, |running_state, _| {
+ let current_panes = running_state.panes.panes();
+ !current_panes.contains(&&tab.pane)
+ || current_panes.len() > 1
+ || (!is_current_pane || pane.items_len() > 1)
+ })
+ .ok()
+ else {
+ return false;
};
- if let Some(item) = item {
- return item.downcast::<SubView>().is_some();
+ if can_drag_away {
+ let item = if is_current_pane {
+ pane.item_for_index(tab.ix)
+ } else {
+ tab.pane.read(cx).item_for_index(tab.ix)
+ };
+ if let Some(item) = item {
+ return item.downcast::<SubView>().is_some();
+ }
}
}
+ false
}
- false
})));
pane.display_nav_history_buttons(None);
pane.set_custom_drop_handle(cx, custom_drop_handle);
pane.set_should_display_tab_bar(|_, _| true);
pane.set_render_tab_bar_buttons(cx, |_, _, _| (None, None));
- pane.set_render_tab_bar(cx, |pane, window, cx| {
- let active_pane_item = pane.active_item();
- h_flex()
- .w_full()
- .px_2()
- .gap_1()
- .h(Tab::container_height(cx))
- .drag_over::<DraggedTab>(|bar, _, _, cx| {
- bar.bg(cx.theme().colors().drop_target_background)
- })
- .on_drop(
- cx.listener(move |this, dragged_tab: &DraggedTab, window, cx| {
- this.drag_split_direction = None;
- this.handle_tab_drop(dragged_tab, this.items_len(), window, cx)
- }),
- )
- .bg(cx.theme().colors().tab_bar_background)
- .border_b_1()
- .border_color(cx.theme().colors().border)
- .children(pane.items().enumerate().map(|(ix, item)| {
- let selected = active_pane_item
- .as_ref()
- .map_or(false, |active| active.item_id() == item.item_id());
- let item_ = item.boxed_clone();
- div()
- .id(SharedString::from(format!(
- "debugger_tab_{}",
- item.item_id().as_u64()
- )))
- .p_1()
- .rounded_md()
- .cursor_pointer()
- .map(|this| {
- if selected {
- this.bg(cx.theme().colors().tab_active_background)
+ pane.set_render_tab_bar(cx, {
+ move |pane, window, cx| {
+ let active_pane_item = pane.active_item();
+ h_flex()
+ .justify_between()
+ .bg(cx.theme().colors().tab_bar_background)
+ .border_b_1()
+ .border_color(cx.theme().colors().border)
+ .track_focus(&focus_handle)
+ .child(
+ h_flex()
+ .w_full()
+ .px_2()
+ .gap_1()
+ .h(Tab::container_height(cx))
+ .drag_over::<DraggedTab>(|bar, _, _, cx| {
+ bar.bg(cx.theme().colors().drop_target_background)
+ })
+ .on_drop(cx.listener(
+ move |this, dragged_tab: &DraggedTab, window, cx| {
+ this.drag_split_direction = None;
+ this.handle_tab_drop(dragged_tab, this.items_len(), window, cx)
+ },
+ ))
+ .children(pane.items().enumerate().map(|(ix, item)| {
+ let selected = active_pane_item
+ .as_ref()
+ .map_or(false, |active| active.item_id() == item.item_id());
+ let item_ = item.boxed_clone();
+ div()
+ .id(SharedString::from(format!(
+ "debugger_tab_{}",
+ item.item_id().as_u64()
+ )))
+ .p_1()
+ .rounded_md()
+ .cursor_pointer()
+ .map(|this| {
+ if selected {
+ this.bg(cx.theme().colors().tab_active_background)
+ } else {
+ let hover_color = cx.theme().colors().element_hover;
+ this.hover(|style| style.bg(hover_color))
+ }
+ })
+ .on_click(cx.listener(move |this, _, window, cx| {
+ let index = this.index_for_item(&*item_);
+ if let Some(index) = index {
+ this.activate_item(index, true, true, window, cx);
+ }
+ }))
+ .child(item.tab_content(
+ TabContentParams {
+ selected,
+ ..Default::default()
+ },
+ window,
+ cx,
+ ))
+ .on_drop(cx.listener(
+ move |this, dragged_tab: &DraggedTab, window, cx| {
+ this.drag_split_direction = None;
+ this.handle_tab_drop(dragged_tab, ix, window, cx)
+ },
+ ))
+ .on_drag(
+ DraggedTab {
+ item: item.boxed_clone(),
+ pane: cx.entity().clone(),
+ detail: 0,
+ is_active: selected,
+ ix,
+ },
+ |tab, _, _, cx| cx.new(|_| tab.clone()),
+ )
+ })),
+ )
+ .child({
+ let zoomed = pane.is_zoomed();
+ IconButton::new(
+ "debug-toggle-zoom",
+ if zoomed {
+ IconName::Minimize
} else {
- let hover_color = cx.theme().colors().element_hover;
- this.hover(|style| style.bg(hover_color))
- }
- })
- .on_click(cx.listener(move |this, _, window, cx| {
- let index = this.index_for_item(&*item_);
- if let Some(index) = index {
- this.activate_item(index, true, true, window, cx);
- }
- }))
- .child(item.tab_content(
- TabContentParams {
- selected,
- ..Default::default()
- },
- window,
- cx,
- ))
- .on_drop(
- cx.listener(move |this, dragged_tab: &DraggedTab, window, cx| {
- this.drag_split_direction = None;
- this.handle_tab_drop(dragged_tab, ix, window, cx)
- }),
- )
- .on_drag(
- DraggedTab {
- item: item.boxed_clone(),
- pane: cx.entity().clone(),
- detail: 0,
- is_active: selected,
- ix,
+ IconName::Maximize
},
- |tab, _, _, cx| cx.new(|_| tab.clone()),
)
- }))
- .into_any_element()
+ .icon_size(IconSize::Small)
+ .on_click(cx.listener(move |pane, _, window, cx| {
+ pane.toggle_zoom(&workspace::ToggleZoom, window, cx);
+ }))
+ .tooltip({
+ let focus_handle = focus_handle.clone();
+ move |window, cx| {
+ let zoomed_text = if zoomed { "Zoom Out" } else { "Zoom In" };
+ Tooltip::for_action_in(
+ zoomed_text,
+ &workspace::ToggleZoom,
+ &focus_handle,
+ window,
+ cx,
+ )
+ }
+ })
+ })
+ .into_any_element()
+ }
});
pane
});
@@ -730,10 +778,25 @@ impl RunningState {
cx: &mut Context<RunningState>,
) {
this.serialize_layout(window, cx);
- if let Event::Remove { .. } = event {
- let _did_find_pane = this.panes.remove(&source_pane).is_ok();
- debug_assert!(_did_find_pane);
- cx.notify();
+ match event {
+ Event::Remove { .. } => {
+ let _did_find_pane = this.panes.remove(&source_pane).is_ok();
+ debug_assert!(_did_find_pane);
+ cx.notify();
+ }
+ Event::ZoomIn => {
+ source_pane.update(cx, |pane, cx| {
+ pane.set_zoomed(true, cx);
+ });
+ cx.notify();
+ }
+ Event::ZoomOut => {
+ source_pane.update(cx, |pane, cx| {
+ pane.set_zoomed(false, cx);
+ });
+ cx.notify();
+ }
+ _ => {}
}
}