context_strip.rs

  1use std::rc::Rc;
  2
  3use gpui::{FocusHandle, Model, View, WeakModel, WeakView};
  4use ui::{prelude::*, PopoverMenu, PopoverMenuHandle, Tooltip};
  5use workspace::Workspace;
  6
  7use crate::context_picker::ContextPicker;
  8use crate::context_store::ContextStore;
  9use crate::thread_store::ThreadStore;
 10use crate::ui::ContextPill;
 11use crate::ToggleContextPicker;
 12
 13pub struct ContextStrip {
 14    context_store: Model<ContextStore>,
 15    context_picker: View<ContextPicker>,
 16    context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
 17    focus_handle: FocusHandle,
 18}
 19
 20impl ContextStrip {
 21    pub fn new(
 22        context_store: Model<ContextStore>,
 23        workspace: WeakView<Workspace>,
 24        thread_store: Option<WeakModel<ThreadStore>>,
 25        focus_handle: FocusHandle,
 26        context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
 27        cx: &mut ViewContext<Self>,
 28    ) -> Self {
 29        Self {
 30            context_store: context_store.clone(),
 31            context_picker: cx.new_view(|cx| {
 32                ContextPicker::new(
 33                    workspace.clone(),
 34                    thread_store.clone(),
 35                    context_store.downgrade(),
 36                    cx,
 37                )
 38            }),
 39            context_picker_menu_handle,
 40            focus_handle,
 41        }
 42    }
 43}
 44
 45impl Render for ContextStrip {
 46    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
 47        let context = self.context_store.read(cx).context();
 48        let context_picker = self.context_picker.clone();
 49        let focus_handle = self.focus_handle.clone();
 50
 51        h_flex()
 52            .flex_wrap()
 53            .gap_1()
 54            .child(
 55                PopoverMenu::new("context-picker")
 56                    .menu(move |_cx| Some(context_picker.clone()))
 57                    .trigger(
 58                        IconButton::new("add-context", IconName::Plus)
 59                            .icon_size(IconSize::Small)
 60                            .style(ui::ButtonStyle::Filled)
 61                            .tooltip(move |cx| {
 62                                Tooltip::for_action_in(
 63                                    "Add Context",
 64                                    &ToggleContextPicker,
 65                                    &focus_handle,
 66                                    cx,
 67                                )
 68                            }),
 69                    )
 70                    .attach(gpui::Corner::TopLeft)
 71                    .anchor(gpui::Corner::BottomLeft)
 72                    .offset(gpui::Point {
 73                        x: px(0.0),
 74                        y: px(-16.0),
 75                    })
 76                    .with_handle(self.context_picker_menu_handle.clone()),
 77            )
 78            .children(context.iter().map(|context| {
 79                ContextPill::new(context.clone()).on_remove({
 80                    let context = context.clone();
 81                    let context_store = self.context_store.clone();
 82                    Rc::new(cx.listener(move |_this, _event, cx| {
 83                        context_store.update(cx, |this, _cx| {
 84                            this.remove_context(&context.id);
 85                        });
 86                        cx.notify();
 87                    }))
 88                })
 89            }))
 90            .when(!context.is_empty(), |parent| {
 91                parent.child(
 92                    IconButton::new("remove-all-context", IconName::Eraser)
 93                        .icon_size(IconSize::Small)
 94                        .tooltip(move |cx| Tooltip::text("Remove All Context", cx))
 95                        .on_click({
 96                            let context_store = self.context_store.clone();
 97                            cx.listener(move |_this, _event, cx| {
 98                                context_store.update(cx, |this, _cx| this.clear());
 99                                cx.notify();
100                            })
101                        }),
102                )
103            })
104    }
105}