prefs.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
  2. /* exported init, buildPrefsWidget */
  3. import GLib from 'gi://GLib';
  4. import GObject from 'gi://GObject';
  5. import Gio from 'gi://Gio';
  6. import Gtk from 'gi://Gtk';
  7. import {
  8. ExtensionPreferences,
  9. gettext as _
  10. } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
  11. const AppIndicatorPreferences = GObject.registerClass(
  12. class AppIndicatorPreferences extends Gtk.Box {
  13. _init(extension) {
  14. super._init({orientation: Gtk.Orientation.VERTICAL, spacing: 30});
  15. this._settings = extension.getSettings();
  16. let label = null;
  17. let widget = null;
  18. this.preferences_vbox = new Gtk.Box({
  19. orientation: Gtk.Orientation.VERTICAL,
  20. spacing: 8,
  21. margin_start: 30,
  22. margin_end: 30,
  23. margin_top: 30,
  24. margin_bottom: 30,
  25. });
  26. this.custom_icons_vbox = new Gtk.Box({
  27. orientation: Gtk.Orientation.HORIZONTAL,
  28. spacing: 10,
  29. margin_start: 10,
  30. margin_end: 10,
  31. margin_top: 10,
  32. margin_bottom: 10,
  33. });
  34. label = new Gtk.Label({
  35. label: _('Enable Legacy Tray Icons support'),
  36. hexpand: true,
  37. halign: Gtk.Align.START,
  38. });
  39. widget = new Gtk.Switch({halign: Gtk.Align.END});
  40. this._settings.bind('legacy-tray-enabled', widget, 'active',
  41. Gio.SettingsBindFlags.DEFAULT);
  42. this.legacy_tray_hbox = new Gtk.Box({
  43. orientation: Gtk.Orientation.HORIZONTAL,
  44. spacing: 10,
  45. margin_start: 10,
  46. margin_end: 10,
  47. margin_top: 10,
  48. margin_bottom: 10,
  49. });
  50. this.legacy_tray_hbox.append(label);
  51. this.legacy_tray_hbox.append(widget);
  52. // Icon opacity
  53. this.opacity_hbox = new Gtk.Box({
  54. orientation: Gtk.Orientation.HORIZONTAL,
  55. spacing: 10,
  56. margin_start: 10,
  57. margin_end: 10,
  58. margin_top: 10,
  59. margin_bottom: 10,
  60. });
  61. label = new Gtk.Label({
  62. label: _('Opacity (min: 0, max: 255)'),
  63. hexpand: true,
  64. halign: Gtk.Align.START,
  65. });
  66. widget = new Gtk.SpinButton({halign: Gtk.Align.END});
  67. widget.set_sensitive(true);
  68. widget.set_range(0, 255);
  69. widget.set_value(this._settings.get_int('icon-opacity'));
  70. widget.set_increments(1, 2);
  71. widget.connect('value-changed', w => {
  72. this._settings.set_int('icon-opacity', w.get_value_as_int());
  73. });
  74. this.opacity_hbox.append(label);
  75. this.opacity_hbox.append(widget);
  76. // Icon saturation
  77. this.saturation_hbox = new Gtk.Box({
  78. orientation: Gtk.Orientation.HORIZONTAL,
  79. spacing: 10,
  80. margin_start: 10,
  81. margin_end: 10,
  82. margin_top: 10,
  83. margin_bottom: 10,
  84. });
  85. label = new Gtk.Label({
  86. label: _('Desaturation (min: 0.0, max: 1.0)'),
  87. hexpand: true,
  88. halign: Gtk.Align.START,
  89. });
  90. widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1});
  91. widget.set_sensitive(true);
  92. widget.set_range(0.0, 1.0);
  93. widget.set_value(this._settings.get_double('icon-saturation'));
  94. widget.set_increments(0.1, 0.2);
  95. widget.connect('value-changed', w => {
  96. this._settings.set_double('icon-saturation', w.get_value());
  97. });
  98. this.saturation_hbox.append(label);
  99. this.saturation_hbox.append(widget);
  100. // Icon brightness
  101. this.brightness_hbox = new Gtk.Box({
  102. orientation: Gtk.Orientation.HORIZONTAL,
  103. spacing: 10,
  104. margin_start: 10,
  105. margin_end: 10,
  106. margin_top: 10,
  107. margin_bottom: 10,
  108. });
  109. label = new Gtk.Label({
  110. label: _('Brightness (min: -1.0, max: 1.0)'),
  111. hexpand: true,
  112. halign: Gtk.Align.START,
  113. });
  114. widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1});
  115. widget.set_sensitive(true);
  116. widget.set_range(-1.0, 1.0);
  117. widget.set_value(this._settings.get_double('icon-brightness'));
  118. widget.set_increments(0.1, 0.2);
  119. widget.connect('value-changed', w => {
  120. this._settings.set_double('icon-brightness', w.get_value());
  121. });
  122. this.brightness_hbox.append(label);
  123. this.brightness_hbox.append(widget);
  124. // Icon contrast
  125. this.contrast_hbox = new Gtk.Box({
  126. orientation: Gtk.Orientation.HORIZONTAL,
  127. spacing: 10,
  128. margin_start: 10,
  129. margin_end: 10,
  130. margin_top: 10,
  131. margin_bottom: 10,
  132. });
  133. label = new Gtk.Label({
  134. label: _('Contrast (min: -1.0, max: 1.0)'),
  135. hexpand: true,
  136. halign: Gtk.Align.START,
  137. });
  138. widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1});
  139. widget.set_sensitive(true);
  140. widget.set_range(-1.0, 1.0);
  141. widget.set_value(this._settings.get_double('icon-contrast'));
  142. widget.set_increments(0.1, 0.2);
  143. widget.connect('value-changed', w => {
  144. this._settings.set_double('icon-contrast', w.get_value());
  145. });
  146. this.contrast_hbox.append(label);
  147. this.contrast_hbox.append(widget);
  148. // Icon size
  149. this.icon_size_hbox = new Gtk.Box({
  150. orientation: Gtk.Orientation.HORIZONTAL,
  151. spacing: 10,
  152. margin_start: 10,
  153. margin_end: 10,
  154. margin_top: 10,
  155. margin_bottom: 10,
  156. });
  157. label = new Gtk.Label({
  158. label: _('Icon size (min: 0, max: 96)'),
  159. hexpand: true,
  160. halign: Gtk.Align.START,
  161. });
  162. widget = new Gtk.SpinButton({halign: Gtk.Align.END});
  163. widget.set_sensitive(true);
  164. widget.set_range(0, 96);
  165. widget.set_value(this._settings.get_int('icon-size'));
  166. widget.set_increments(1, 2);
  167. widget.connect('value-changed', w => {
  168. this._settings.set_int('icon-size', w.get_value_as_int());
  169. });
  170. this.icon_size_hbox.append(label);
  171. this.icon_size_hbox.append(widget);
  172. // Tray position in panel
  173. this.tray_position_hbox = new Gtk.Box({
  174. orientation: Gtk.Orientation.HORIZONTAL,
  175. spacing: 10,
  176. margin_start: 10,
  177. margin_end: 10,
  178. margin_top: 10,
  179. margin_bottom: 10,
  180. });
  181. label = new Gtk.Label({
  182. label: _('Tray horizontal alignment'),
  183. hexpand: true,
  184. halign: Gtk.Align.START,
  185. });
  186. widget = new Gtk.ComboBoxText();
  187. widget.append('center', _('Center'));
  188. widget.append('left', _('Left'));
  189. widget.append('right', _('Right'));
  190. this._settings.bind('tray-pos', widget, 'active-id',
  191. Gio.SettingsBindFlags.DEFAULT);
  192. this.tray_position_hbox.append(label);
  193. this.tray_position_hbox.append(widget);
  194. this.preferences_vbox.append(this.legacy_tray_hbox);
  195. this.preferences_vbox.append(this.opacity_hbox);
  196. this.preferences_vbox.append(this.saturation_hbox);
  197. this.preferences_vbox.append(this.brightness_hbox);
  198. this.preferences_vbox.append(this.contrast_hbox);
  199. this.preferences_vbox.append(this.icon_size_hbox);
  200. this.preferences_vbox.append(this.tray_position_hbox);
  201. // Custom icons section
  202. const customListStore = new Gtk.ListStore();
  203. customListStore.set_column_types([
  204. GObject.TYPE_STRING,
  205. GObject.TYPE_STRING,
  206. GObject.TYPE_STRING,
  207. ]);
  208. const customInitArray = this._settings.get_value('custom-icons').deep_unpack();
  209. customInitArray.forEach(pair => {
  210. customListStore.set(customListStore.append(), [0, 1, 2], pair);
  211. });
  212. customListStore.append();
  213. const customTreeView = new Gtk.TreeView({
  214. model: customListStore,
  215. hexpand: true,
  216. vexpand: true,
  217. });
  218. const customTitles = [
  219. _('Indicator ID'),
  220. _('Icon Name'),
  221. _('Attention Icon Name'),
  222. ];
  223. const indicatorIdColumn = new Gtk.TreeViewColumn({
  224. title: customTitles[0],
  225. sizing: Gtk.TreeViewColumnSizing.AUTOSIZE,
  226. });
  227. const customIconColumn = new Gtk.TreeViewColumn({
  228. title: customTitles[1],
  229. sizing: Gtk.TreeViewColumnSizing.AUTOSIZE,
  230. });
  231. const customAttentionIconColumn = new Gtk.TreeViewColumn({
  232. title: customTitles[2],
  233. sizing: Gtk.TreeViewColumnSizing.AUTOSIZE,
  234. });
  235. const cellrenderer = new Gtk.CellRendererText({editable: true});
  236. indicatorIdColumn.pack_start(cellrenderer, true);
  237. customIconColumn.pack_start(cellrenderer, true);
  238. customAttentionIconColumn.pack_start(cellrenderer, true);
  239. indicatorIdColumn.add_attribute(cellrenderer, 'text', 0);
  240. customIconColumn.add_attribute(cellrenderer, 'text', 1);
  241. customAttentionIconColumn.add_attribute(cellrenderer, 'text', 2);
  242. customTreeView.insert_column(indicatorIdColumn, 0);
  243. customTreeView.insert_column(customIconColumn, 1);
  244. customTreeView.insert_column(customAttentionIconColumn, 2);
  245. customTreeView.set_grid_lines(Gtk.TreeViewGridLines.BOTH);
  246. this.custom_icons_vbox.append(customTreeView);
  247. cellrenderer.connect('edited', (w, path, text) => {
  248. this.selection = customTreeView.get_selection();
  249. const title = customTreeView.get_cursor()[1].get_title();
  250. const columnIndex = customTitles.indexOf(title);
  251. const selection = this.selection.get_selected();
  252. const iter = selection.at(2);
  253. const text2 = customListStore.get_value(iter, columnIndex ? 0 : 1);
  254. customListStore.set(iter, [columnIndex], [text]);
  255. const storeLength = customListStore.iter_n_children(null);
  256. const customIconArray = [];
  257. for (let i = 0; i < storeLength; i++) {
  258. const returnIter = customListStore.iter_nth_child(null, i);
  259. const [success, iterList] = returnIter;
  260. if (!success)
  261. break;
  262. if (iterList) {
  263. const id = customListStore.get_value(iterList, 0);
  264. const customIcon = customListStore.get_value(iterList, 1);
  265. const customAttentionIcon = customListStore.get_value(iterList, 2);
  266. if (id && customIcon)
  267. customIconArray.push([id, customIcon, customAttentionIcon || '']);
  268. } else {
  269. break;
  270. }
  271. }
  272. this._settings.set_value('custom-icons', new GLib.Variant(
  273. 'a(sss)', customIconArray));
  274. if (storeLength === 1 && (text || text2))
  275. customListStore.append();
  276. if (storeLength > 1) {
  277. if ((!text && !text2) && (storeLength - 1 > path))
  278. customListStore.remove(iter);
  279. if ((text || text2) && storeLength - 1 <= path)
  280. customListStore.append();
  281. }
  282. });
  283. this.notebook = new Gtk.Notebook();
  284. this.notebook.append_page(this.preferences_vbox,
  285. new Gtk.Label({label: _('Preferences')}));
  286. this.notebook.append_page(this.custom_icons_vbox,
  287. new Gtk.Label({label: _('Custom Icons')}));
  288. this.append(this.notebook);
  289. }
  290. });
  291. export default class DockPreferences extends ExtensionPreferences {
  292. getPreferencesWidget() {
  293. return new AppIndicatorPreferences(this);
  294. }
  295. }