1use editor::Editor;
2use encoding::Encoding;
3use encoding::all::{
4 BIG5_2003, EUC_JP, GB18030, GBK, HZ, IBM866, ISO_2022_JP, ISO_8859_1, ISO_8859_2, ISO_8859_3,
5 ISO_8859_4, ISO_8859_5, ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_10, ISO_8859_13,
6 ISO_8859_14, ISO_8859_15, ISO_8859_16, KOI8_R, KOI8_U, MAC_CYRILLIC, MAC_ROMAN, UTF_8,
7 UTF_16BE, UTF_16LE, WINDOWS_874, WINDOWS_949, WINDOWS_1250, WINDOWS_1251, WINDOWS_1252,
8 WINDOWS_1253, WINDOWS_1254, WINDOWS_1255, WINDOWS_1256, WINDOWS_1257, WINDOWS_1258,
9};
10use gpui::{ClickEvent, Entity, Subscription, WeakEntity};
11use ui::{Button, ButtonCommon, Context, LabelSize, Render, Tooltip, Window, div};
12use ui::{Clickable, ParentElement};
13use workspace::{ItemHandle, StatusItemView, Workspace};
14
15use crate::selectors::save_or_reopen::{EncodingSaveOrReopenSelector, get_current_encoding};
16
17/// A status bar item that shows the current file encoding and allows changing it.
18pub struct EncodingIndicator {
19 pub encoding: Option<&'static dyn Encoding>,
20 pub workspace: WeakEntity<Workspace>,
21 observe: Option<Subscription>, // Subscription to observe changes in the active editor
22}
23
24pub mod selectors;
25
26impl Render for EncodingIndicator {
27 fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl ui::IntoElement {
28 let status_element = div();
29
30 status_element.child(
31 Button::new("encoding", encoding_name(self.encoding.unwrap_or(UTF_8)))
32 .label_size(LabelSize::Small)
33 .tooltip(Tooltip::text("Select Encoding"))
34 .on_click(cx.listener(|indicator, _: &ClickEvent, window, cx| {
35 if let Some(workspace) = indicator.workspace.upgrade() {
36 workspace.update(cx, |workspace, cx| {
37 EncodingSaveOrReopenSelector::toggle(workspace, window, cx)
38 })
39 } else {
40 }
41 })),
42 )
43 }
44}
45
46impl EncodingIndicator {
47 pub fn get_current_encoding(&self, cx: &mut Context<Self>, editor: WeakEntity<Editor>) {}
48
49 pub fn new(
50 encoding: Option<&'static dyn encoding::Encoding>,
51 workspace: WeakEntity<Workspace>,
52 observe: Option<Subscription>,
53 ) -> EncodingIndicator {
54 EncodingIndicator {
55 encoding,
56 workspace,
57 observe,
58 }
59 }
60
61 pub fn update(
62 &mut self,
63 editor: Entity<Editor>,
64 _: &mut Window,
65 cx: &mut Context<EncodingIndicator>,
66 ) {
67 let editor = editor.read(cx);
68 if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
69 let encoding = buffer.read(cx).encoding;
70 self.encoding = Some(encoding);
71 }
72
73 cx.notify();
74 }
75}
76
77impl StatusItemView for EncodingIndicator {
78 fn set_active_pane_item(
79 &mut self,
80 active_pane_item: Option<&dyn ItemHandle>,
81 window: &mut Window,
82 cx: &mut Context<Self>,
83 ) {
84 match active_pane_item.and_then(|item| item.downcast::<Editor>()) {
85 Some(editor) => {
86 self.observe = Some(cx.observe_in(&editor, window, Self::update));
87 self.update(editor, window, cx);
88 }
89 None => {
90 self.encoding = None;
91 self.observe = None;
92 }
93 }
94 }
95}
96
97/// Get a human-readable name for the given encoding.
98pub fn encoding_name(encoding: &'static dyn Encoding) -> String {
99 let name = encoding.name();
100
101 match () {
102 () if name == UTF_8.name() => "UTF-8",
103 () if name == UTF_16LE.name() => "UTF-16 LE",
104 () if name == UTF_16BE.name() => "UTF-16 BE",
105 () if name == IBM866.name() => "IBM866",
106 () if name == ISO_8859_1.name() => "ISO 8859-1",
107 () if name == ISO_8859_2.name() => "ISO 8859-2",
108 () if name == ISO_8859_3.name() => "ISO 8859-3",
109 () if name == ISO_8859_4.name() => "ISO 8859-4",
110 () if name == ISO_8859_5.name() => "ISO 8859-5",
111 () if name == ISO_8859_6.name() => "ISO 8859-6",
112 () if name == ISO_8859_7.name() => "ISO 8859-7",
113 () if name == ISO_8859_8.name() => "ISO 8859-8",
114 () if name == ISO_8859_10.name() => "ISO 8859-10",
115 () if name == ISO_8859_13.name() => "ISO 8859-13",
116 () if name == ISO_8859_14.name() => "ISO 8859-14",
117 () if name == ISO_8859_15.name() => "ISO 8859-15",
118 () if name == ISO_8859_16.name() => "ISO 8859-16",
119 () if name == KOI8_R.name() => "KOI8-R",
120 () if name == KOI8_U.name() => "KOI8-U",
121 () if name == MAC_ROMAN.name() => "MacRoman",
122 () if name == MAC_CYRILLIC.name() => "Mac Cyrillic",
123 () if name == WINDOWS_874.name() => "Windows-874",
124 () if name == WINDOWS_1250.name() => "Windows-1250",
125 () if name == WINDOWS_1251.name() => "Windows-1251",
126 () if name == WINDOWS_1252.name() => "Windows-1252",
127 () if name == WINDOWS_1253.name() => "Windows-1253",
128 () if name == WINDOWS_1254.name() => "Windows-1254",
129 () if name == WINDOWS_1255.name() => "Windows-1255",
130 () if name == WINDOWS_1256.name() => "Windows-1256",
131 () if name == WINDOWS_1257.name() => "Windows-1257",
132 () if name == WINDOWS_1258.name() => "Windows-1258",
133 () if name == WINDOWS_949.name() => "Windows-949",
134 () if name == EUC_JP.name() => "EUC-JP",
135 () if name == ISO_2022_JP.name() => "ISO 2022-JP",
136 () if name == GBK.name() => "GBK",
137 () if name == GB18030.name() => "GB18030",
138 () if name == BIG5_2003.name() => "Big5",
139 () if name == HZ.name() => "HZ-GB-2312",
140 _ => "",
141 }
142 .to_string()
143}
144
145/// Get an encoding from its index in the predefined list.
146/// If the index is out of range, UTF-8 is returned as a default.
147pub fn encoding_from_index(index: usize) -> &'static dyn Encoding {
148 match index {
149 0 => UTF_8,
150 1 => UTF_16LE,
151 2 => UTF_16BE,
152 3 => IBM866,
153 4 => ISO_8859_1,
154 5 => ISO_8859_2,
155 6 => ISO_8859_3,
156 7 => ISO_8859_4,
157 8 => ISO_8859_5,
158 9 => ISO_8859_6,
159 10 => ISO_8859_7,
160 11 => ISO_8859_8,
161 12 => ISO_8859_10,
162 13 => ISO_8859_13,
163 14 => ISO_8859_14,
164 15 => ISO_8859_15,
165 16 => ISO_8859_16,
166 17 => KOI8_R,
167 18 => KOI8_U,
168 19 => MAC_ROMAN,
169 20 => MAC_CYRILLIC,
170 21 => WINDOWS_874,
171 22 => WINDOWS_1250,
172 23 => WINDOWS_1251,
173 24 => WINDOWS_1252,
174 25 => WINDOWS_1253,
175 26 => WINDOWS_1254,
176 27 => WINDOWS_1255,
177 28 => WINDOWS_1256,
178 29 => WINDOWS_1257,
179 30 => WINDOWS_1258,
180 31 => WINDOWS_949,
181 32 => EUC_JP,
182 33 => ISO_2022_JP,
183 34 => GBK,
184 35 => GB18030,
185 36 => BIG5_2003,
186 37 => HZ,
187 _ => UTF_8,
188 }
189}