@@ -2647,6 +2647,24 @@ impl Pane {
let is_pinned = self.is_tab_pinned(ix);
let position_relative_to_active_item = ix.cmp(&self.active_item_index);
+ let read_only_toggle = || {
+ IconButton::new("toggle_read_only", IconName::FileLock)
+ .size(ButtonSize::None)
+ .shape(IconButtonShape::Square)
+ .icon_color(Color::Muted)
+ .icon_size(IconSize::Small)
+ .tooltip(move |_, cx| {
+ Tooltip::with_meta("Unlock File", None, "This will make this file editable", cx)
+ })
+ .on_click(cx.listener(move |pane, _, window, cx| {
+ if let Some(item) = pane.item_for_index(ix) {
+ item.toggle_read_only(window, cx);
+ }
+ }))
+ };
+
+ let has_file_icon = icon.is_some() | decorated_icon.is_some();
+
let tab = Tab::new(ix)
.position(if is_first_item {
TabPosition::First
@@ -2781,30 +2799,36 @@ impl Pane {
})
.child(
h_flex()
+ .id(("pane-tab-content", ix))
.gap_1()
- .items_center()
.children(if let Some(decorated_icon) = decorated_icon {
- Some(div().child(decorated_icon.into_any_element()))
+ Some(decorated_icon.into_any_element())
+ } else if let Some(icon) = icon {
+ Some(icon.into_any_element())
+ } else if item.is_read_only(cx) {
+ Some(read_only_toggle().into_any_element())
} else {
- icon.map(|icon| div().child(icon.into_any_element()))
+ None
})
.child(label)
- .id(("pane-tab-content", ix))
.map(|this| match tab_tooltip_content {
- Some(TabTooltipContent::Text(text)) => this.tooltip(Tooltip::text(text)),
+ Some(TabTooltipContent::Text(text)) => {
+ if item.is_read_only(cx) {
+ this.tooltip(move |_, cx| {
+ let text = text.clone();
+ Tooltip::with_meta(text, None, "Read-Only File", cx)
+ })
+ } else {
+ this.tooltip(Tooltip::text(text))
+ }
+ }
Some(TabTooltipContent::Custom(element_fn)) => {
this.tooltip(move |window, cx| element_fn(window, cx))
}
None => this,
})
- .children(if item.is_read_only(cx) {
- Some(
- Icon::new(IconName::FileLock)
- .color(Color::Muted)
- .size(IconSize::Small),
- )
- } else {
- None
+ .when(item.is_read_only(cx) && has_file_icon, |this| {
+ this.child(read_only_toggle())
}),
);
@@ -2821,8 +2845,11 @@ impl Pane {
let has_items_to_right = ix < total_items - 1;
let has_clean_items = self.items.iter().any(|item| !item.is_dirty(cx));
let is_pinned = self.is_tab_pinned(ix);
+ let is_read_only = item.is_read_only(cx);
+
let pane = cx.entity().downgrade();
let menu_context = item.item_focus_handle(cx);
+
right_click_menu(ix)
.trigger(|_, _, _| tab)
.menu(move |window, cx| {
@@ -2969,6 +2996,22 @@ impl Pane {
}
})
};
+
+ let read_only_label = if is_read_only {
+ "Make File Editable"
+ } else {
+ "Make File Read-Only"
+ };
+ menu = menu.separator().entry(
+ read_only_label,
+ None,
+ window.handler_for(&pane, move |pane, window, cx| {
+ if let Some(item) = pane.item_for_index(ix) {
+ item.toggle_read_only(window, cx);
+ }
+ }),
+ );
+
if let Some(entry) = single_entry_to_resolve {
let project_path = pane
.read(cx)
@@ -3000,6 +3043,7 @@ impl Pane {
&& worktree.is_some_and(|worktree| worktree.read(cx).is_visible());
let entry_id = entry.to_proto();
+
menu = menu
.separator()
.when_some(entry_abs_path, |menu, abs_path| {
@@ -3064,7 +3108,7 @@ impl Pane {
} else {
menu = menu.map(pin_tab_entries);
}
- }
+ };
menu.context(menu_context)
})