1use gpui::ElementId;
2use ui::{Tooltip, prelude::*};
3
4use crate::{
5 CsvPreviewView,
6 settings::FontType,
7 table_data_engine::sorting_by_column::{AppliedSorting, SortDirection},
8 types::AnyColumn,
9};
10
11impl CsvPreviewView {
12 /// Create header for data, which is orderable with text on the left and sort button on the right
13 pub(crate) fn create_header_element_with_sort_button(
14 &self,
15 header_text: SharedString,
16 cx: &mut Context<'_, CsvPreviewView>,
17 col_idx: AnyColumn,
18 ) -> AnyElement {
19 // CSV data columns: text + filter/sort buttons
20 h_flex()
21 .justify_between()
22 .items_center()
23 .w_full()
24 .map(|div| match self.settings.font_type {
25 FontType::Ui => div.font_ui(cx),
26 FontType::Monospace => div.font_buffer(cx),
27 })
28 .child(div().child(header_text))
29 .child(h_flex().gap_1().child(self.create_sort_button(cx, col_idx)))
30 .into_any_element()
31 }
32
33 fn create_sort_button(
34 &self,
35 cx: &mut Context<'_, CsvPreviewView>,
36 col_idx: AnyColumn,
37 ) -> Button {
38 let sort_btn = Button::new(
39 ElementId::NamedInteger("sort-button".into(), col_idx.get() as u64),
40 match self.engine.applied_sorting {
41 Some(ordering) if ordering.col_idx == col_idx => match ordering.direction {
42 SortDirection::Asc => "↓",
43 SortDirection::Desc => "↑",
44 },
45 _ => "↕", // Unsorted/available for sorting
46 },
47 )
48 .size(ButtonSize::Compact)
49 .style(
50 if self
51 .engine
52 .applied_sorting
53 .is_some_and(|o| o.col_idx == col_idx)
54 {
55 ButtonStyle::Filled
56 } else {
57 ButtonStyle::Subtle
58 },
59 )
60 .tooltip(Tooltip::text(match self.engine.applied_sorting {
61 Some(ordering) if ordering.col_idx == col_idx => match ordering.direction {
62 SortDirection::Asc => "Sorted A-Z. Click to sort Z-A",
63 SortDirection::Desc => "Sorted Z-A. Click to disable sorting",
64 },
65 _ => "Not sorted. Click to sort A-Z",
66 }))
67 .on_click(cx.listener(move |this, _event, _window, cx| {
68 let new_sorting = match this.engine.applied_sorting {
69 Some(ordering) if ordering.col_idx == col_idx => {
70 // Same column clicked - cycle through states
71 match ordering.direction {
72 SortDirection::Asc => Some(AppliedSorting {
73 col_idx,
74 direction: SortDirection::Desc,
75 }),
76 SortDirection::Desc => None, // Clear sorting
77 }
78 }
79 _ => {
80 // Different column or no sorting - start with ascending
81 Some(AppliedSorting {
82 col_idx,
83 direction: SortDirection::Asc,
84 })
85 }
86 };
87
88 this.engine.applied_sorting = new_sorting;
89 this.apply_sort();
90 cx.notify();
91 }));
92 sort_btn
93 }
94}