dlg_settings.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. --Minetest
  2. --Copyright (C) 2022 rubenwardy
  3. --
  4. --This program is free software; you can redistribute it and/or modify
  5. --it under the terms of the GNU Lesser General Public License as published by
  6. --the Free Software Foundation; either version 2.1 of the License, or
  7. --(at your option) any later version.
  8. --
  9. --This program is distributed in the hope that it will be useful,
  10. --but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. --GNU Lesser General Public License for more details.
  13. --
  14. --You should have received a copy of the GNU Lesser General Public License along
  15. --with this program; if not, write to the Free Software Foundation, Inc.,
  16. --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. local component_funcs = dofile(core.get_mainmenu_path() .. DIR_DELIM ..
  18. "settings" .. DIR_DELIM .. "components.lua")
  19. local shadows_component = dofile(core.get_mainmenu_path() .. DIR_DELIM ..
  20. "settings" .. DIR_DELIM .. "shadows_component.lua")
  21. local full_settings = settingtypes.parse_config_file(false, true)
  22. local info_icon_path = core.formspec_escape(defaulttexturedir .. "settings_info.png")
  23. local reset_icon_path = core.formspec_escape(defaulttexturedir .. "settings_reset.png")
  24. local gettext = fgettext_ne
  25. local all_pages = {}
  26. local page_by_id = {}
  27. local filtered_pages = all_pages
  28. local filtered_page_by_id = page_by_id
  29. local function add_page(page)
  30. assert(type(page.id) == "string")
  31. assert(type(page.title) == "string")
  32. assert(page.section == nil or type(page.section) == "string")
  33. assert(type(page.content) == "table")
  34. assert(not page_by_id[page.id], "Page " .. page.id .. " already registered")
  35. all_pages[#all_pages + 1] = page
  36. page_by_id[page.id] = page
  37. return page
  38. end
  39. local change_keys = {
  40. query_text = "Change keys",
  41. requires = {
  42. keyboard_mouse = true,
  43. },
  44. get_formspec = function(self, avail_w)
  45. local btn_w = math.min(avail_w, 3)
  46. return ("button[0,0;%f,0.8;btn_change_keys;%s]"):format(btn_w, fgettext("Change keys")), 0.8
  47. end,
  48. on_submit = function(self, fields)
  49. if fields.btn_change_keys then
  50. core.show_keys_menu()
  51. end
  52. end,
  53. }
  54. add_page({
  55. id = "accessibility",
  56. title = gettext("Accessibility"),
  57. content = {
  58. "language",
  59. { heading = gettext("General") },
  60. "font_size",
  61. "chat_font_size",
  62. "gui_scaling",
  63. "hud_scaling",
  64. "show_nametag_backgrounds",
  65. { heading = gettext("Chat") },
  66. "console_height",
  67. "console_alpha",
  68. "console_color",
  69. { heading = gettext("Controls") },
  70. "autojump",
  71. "safe_dig_and_place",
  72. { heading = gettext("Movement") },
  73. "arm_inertia",
  74. "view_bobbing_amount",
  75. "fall_bobbing_amount",
  76. },
  77. })
  78. local function load_settingtypes()
  79. local page = nil
  80. local section = nil
  81. local function ensure_page_started()
  82. if not page then
  83. page = add_page({
  84. id = (section or "general"):lower():gsub(" ", "_"),
  85. title = section or gettext("General"),
  86. section = section,
  87. content = {},
  88. })
  89. end
  90. end
  91. for _, entry in ipairs(full_settings) do
  92. if entry.type == "category" then
  93. if entry.level == 0 then
  94. section = entry.name
  95. page = nil
  96. elseif entry.level == 1 then
  97. page = {
  98. id = ((section and section .. "_" or "") .. entry.name):lower():gsub(" ", "_"),
  99. title = entry.readable_name or entry.name,
  100. section = section,
  101. content = {},
  102. }
  103. if page.title:sub(1, 5) ~= "Hide:" then
  104. page = add_page(page)
  105. end
  106. elseif entry.level == 2 then
  107. ensure_page_started()
  108. page.content[#page.content + 1] = {
  109. heading = gettext(entry.readable_name or entry.name),
  110. }
  111. end
  112. else
  113. ensure_page_started()
  114. page.content[#page.content + 1] = entry.name
  115. end
  116. end
  117. end
  118. load_settingtypes()
  119. table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys)
  120. do
  121. local content = page_by_id.graphics_and_audio_shaders.content
  122. local idx = table.indexof(content, "enable_dynamic_shadows")
  123. table.insert(content, idx, shadows_component)
  124. end
  125. local function get_setting_info(name)
  126. for _, entry in ipairs(full_settings) do
  127. if entry.type ~= "category" and entry.name == name then
  128. return entry
  129. end
  130. end
  131. return nil
  132. end
  133. -- These must not be translated, as they need to show in the local
  134. -- language no matter the user's current language.
  135. -- This list must be kept in sync with src/unsupported_language_list.txt.
  136. get_setting_info("language").option_labels = {
  137. [""] = fgettext_ne("(Use system language)"),
  138. --ar = " [ar]", blacklisted
  139. be = "Беларуская [be]",
  140. bg = "Български [bg]",
  141. ca = "Català [ca]",
  142. cs = "Česky [cs]",
  143. cy = "Cymraeg [cy]",
  144. da = "Dansk [da]",
  145. de = "Deutsch [de]",
  146. --dv = " [dv]", blacklisted
  147. el = "Ελληνικά [el]",
  148. en = "English [en]",
  149. eo = "Esperanto [eo]",
  150. es = "Español [es]",
  151. et = "Eesti [et]",
  152. eu = "Euskara [eu]",
  153. fi = "Suomi [fi]",
  154. fil = "Wikang Filipino [fil]",
  155. fr = "Français [fr]",
  156. gd = "Gàidhlig [gd]",
  157. gl = "Galego [gl]",
  158. --he = " [he]", blacklisted
  159. --hi = " [hi]", blacklisted
  160. hu = "Magyar [hu]",
  161. id = "Bahasa Indonesia [id]",
  162. it = "Italiano [it]",
  163. ja = "日本語 [ja]",
  164. jbo = "Lojban [jbo]",
  165. kk = "Қазақша [kk]",
  166. --kn = " [kn]", blacklisted
  167. ko = "한국어 [ko]",
  168. ky = "Kırgızca / Кыргызча [ky]",
  169. lt = "Lietuvių [lt]",
  170. lv = "Latviešu [lv]",
  171. mn = "Монгол [mn]",
  172. mr = "मराठी [mr]",
  173. ms = "Bahasa Melayu [ms]",
  174. --ms_Arab = " [ms_Arab]", blacklisted
  175. nb = "Norsk Bokmål [nb]",
  176. nl = "Nederlands [nl]",
  177. nn = "Norsk Nynorsk [nn]",
  178. oc = "Occitan [oc]",
  179. pl = "Polski [pl]",
  180. pt = "Português [pt]",
  181. pt_BR = "Português do Brasil [pt_BR]",
  182. ro = "Română [ro]",
  183. ru = "Русский [ru]",
  184. sk = "Slovenčina [sk]",
  185. sl = "Slovenščina [sl]",
  186. sr_Cyrl = "Српски [sr_Cyrl]",
  187. sr_Latn = "Srpski (Latinica) [sr_Latn]",
  188. sv = "Svenska [sv]",
  189. sw = "Kiswahili [sw]",
  190. --th = " [th]", blacklisted
  191. tr = "Türkçe [tr]",
  192. tt = "Tatarça [tt]",
  193. uk = "Українська [uk]",
  194. vi = "Tiếng Việt [vi]",
  195. zh_CN = "中文 (简体) [zh_CN]",
  196. zh_TW = "正體中文 (繁體) [zh_TW]",
  197. }
  198. -- See if setting matches keywords
  199. local function get_setting_match_weight(entry, query_keywords)
  200. local setting_score = 0
  201. for _, keyword in ipairs(query_keywords) do
  202. if string.find(entry.name:lower(), keyword, 1, true) then
  203. setting_score = setting_score + 1
  204. end
  205. if entry.readable_name and
  206. string.find(fgettext(entry.readable_name):lower(), keyword, 1, true) then
  207. setting_score = setting_score + 1
  208. end
  209. if entry.comment and
  210. string.find(fgettext_ne(entry.comment):lower(), keyword, 1, true) then
  211. setting_score = setting_score + 1
  212. end
  213. end
  214. return setting_score
  215. end
  216. local function filter_page_content(page, query_keywords)
  217. if #query_keywords == 0 then
  218. return page.content, 0
  219. end
  220. local retval = {}
  221. local i = 1
  222. local max_weight = 0
  223. for _, content in ipairs(page.content) do
  224. if type(content) == "string" then
  225. local setting = get_setting_info(content)
  226. assert(setting, "Unknown setting: " .. content)
  227. local weight = get_setting_match_weight(setting, query_keywords)
  228. if weight > 0 then
  229. max_weight = math.max(max_weight, weight)
  230. retval[i] = content
  231. i = i + 1
  232. end
  233. elseif type(content) == "table" and content.query_text then
  234. for _, keyword in ipairs(query_keywords) do
  235. if string.find(fgettext(content.query_text), keyword, 1, true) then
  236. max_weight = math.max(max_weight, 1)
  237. retval[i] = content
  238. i = i + 1
  239. break
  240. end
  241. end
  242. end
  243. end
  244. return retval, max_weight
  245. end
  246. local function update_filtered_pages(query)
  247. filtered_pages = {}
  248. filtered_page_by_id = {}
  249. local query_keywords = {}
  250. for word in query:lower():gmatch("%S+") do
  251. table.insert(query_keywords, word)
  252. end
  253. local best_page = nil
  254. local best_page_weight = -1
  255. for _, page in ipairs(all_pages) do
  256. local content, page_weight = filter_page_content(page, query_keywords)
  257. if page_has_contents(page, content) then
  258. local new_page = table.copy(page)
  259. new_page.content = content
  260. filtered_pages[#filtered_pages + 1] = new_page
  261. filtered_page_by_id[new_page.id] = new_page
  262. if page_weight > best_page_weight then
  263. best_page = new_page
  264. best_page_weight = page_weight
  265. end
  266. end
  267. end
  268. return best_page and best_page.id or nil
  269. end
  270. local function check_requirements(name, requires)
  271. if requires == nil then
  272. return true
  273. end
  274. local video_driver = core.get_active_driver()
  275. local shaders_support = video_driver == "opengl" or video_driver == "ogles2"
  276. local special = {
  277. android = PLATFORM == "Android",
  278. desktop = PLATFORM ~= "Android",
  279. touchscreen_gui = TOUCHSCREEN_GUI,
  280. keyboard_mouse = not TOUCHSCREEN_GUI,
  281. shaders_support = shaders_support,
  282. shaders = core.settings:get_bool("enable_shaders") and shaders_support,
  283. opengl = video_driver == "opengl",
  284. gles = video_driver:sub(1, 5) == "ogles",
  285. }
  286. for req_key, req_value in pairs(requires) do
  287. if special[req_key] == nil then
  288. local required_setting = get_setting_info(req_key)
  289. if required_setting == nil then
  290. core.log("warning", "Unknown setting " .. req_key .. " required by " .. name)
  291. end
  292. local actual_value = core.settings:get_bool(req_key,
  293. required_setting and core.is_yes(required_setting.default))
  294. if actual_value ~= req_value then
  295. return false
  296. end
  297. elseif special[req_key] ~= req_value then
  298. return false
  299. end
  300. end
  301. return true
  302. end
  303. function page_has_contents(page, actual_content)
  304. local is_advanced =
  305. page.id:sub(1, #"client_and_server") == "client_and_server" or
  306. page.id:sub(1, #"mapgen") == "mapgen" or
  307. page.id:sub(1, #"advanced") == "advanced"
  308. local show_advanced = core.settings:get_bool("show_advanced")
  309. if is_advanced and not show_advanced then
  310. return false
  311. end
  312. for _, item in ipairs(actual_content) do
  313. if item == false or item.heading then --luacheck: ignore
  314. -- skip
  315. elseif type(item) == "string" then
  316. local setting = get_setting_info(item)
  317. assert(setting, "Unknown setting: " .. item)
  318. if check_requirements(setting.name, setting.requires) then
  319. return true
  320. end
  321. elseif item.get_formspec then
  322. if check_requirements(item.id, item.requires) then
  323. return true
  324. end
  325. else
  326. error("Unknown content in page: " .. dump(item))
  327. end
  328. end
  329. return false
  330. end
  331. local function build_page_components(page)
  332. -- Filter settings based on requirements
  333. local content = {}
  334. local last_heading
  335. for _, item in ipairs(page.content) do
  336. if item == false then --luacheck: ignore
  337. -- skip
  338. elseif item.heading then
  339. last_heading = item
  340. else
  341. local name, requires
  342. if type(item) == "string" then
  343. local setting = get_setting_info(item)
  344. assert(setting, "Unknown setting: " .. item)
  345. name = setting.name
  346. requires = setting.requires
  347. elseif item.get_formspec then
  348. name = item.id
  349. requires = item.requires
  350. else
  351. error("Unknown content in page: " .. dump(item))
  352. end
  353. if check_requirements(name, requires) then
  354. if last_heading then
  355. content[#content + 1] = last_heading
  356. last_heading = nil
  357. end
  358. content[#content + 1] = item
  359. end
  360. end
  361. end
  362. -- Create components
  363. local retval = {}
  364. for i, item in ipairs(content) do
  365. if type(item) == "string" then
  366. local setting = get_setting_info(item)
  367. local component_func = component_funcs[setting.type]
  368. assert(component_func, "Unknown setting type: " .. setting.type)
  369. retval[i] = component_func(setting)
  370. elseif item.get_formspec then
  371. retval[i] = item
  372. elseif item.heading then
  373. retval[i] = component_funcs.heading(item.heading)
  374. end
  375. end
  376. return retval
  377. end
  378. --- Creates a scrollbaroptions for a scroll_container
  379. --
  380. -- @param visible_l the length of the scroll_container and scrollbar
  381. -- @param total_l length of the scrollable area
  382. -- @param scroll_factor as passed to scroll_container
  383. local function make_scrollbaroptions_for_scroll_container(visible_l, total_l, scroll_factor)
  384. assert(total_l >= visible_l)
  385. local max = total_l - visible_l
  386. local thumb_size = (visible_l / total_l) * max
  387. return ("scrollbaroptions[min=0;max=%f;thumbsize=%f]"):format(max / scroll_factor, thumb_size / scroll_factor)
  388. end
  389. local formspec_show_hack = false
  390. local function get_formspec(dialogdata)
  391. local page_id = dialogdata.page_id or "accessibility"
  392. local page = filtered_page_by_id[page_id]
  393. local extra_h = 1 -- not included in tabsize.height
  394. local tabsize = {
  395. width = TOUCHSCREEN_GUI and 16.5 or 15.5,
  396. height = TOUCHSCREEN_GUI and (10 - extra_h) or 12,
  397. }
  398. local scrollbar_w = TOUCHSCREEN_GUI and 0.6 or 0.4
  399. local left_pane_width = TOUCHSCREEN_GUI and 4.5 or 4.25
  400. local search_width = left_pane_width + scrollbar_w - (0.75 * 2)
  401. local back_w = 3
  402. local checkbox_w = (tabsize.width - back_w - 2*0.2) / 2
  403. local show_technical_names = core.settings:get_bool("show_technical_names")
  404. local show_advanced = core.settings:get_bool("show_advanced")
  405. formspec_show_hack = not formspec_show_hack
  406. local fs = {
  407. "formspec_version[6]",
  408. "size[", tostring(tabsize.width), ",", tostring(tabsize.height + extra_h), "]",
  409. TOUCHSCREEN_GUI and "padding[0.01,0.01]" or "",
  410. "bgcolor[#0000]",
  411. -- HACK: this is needed to allow resubmitting the same formspec
  412. formspec_show_hack and " " or "",
  413. "box[0,0;", tostring(tabsize.width), ",", tostring(tabsize.height), ";#0000008C]",
  414. ("button[0,%f;%f,0.8;back;%s]"):format(
  415. tabsize.height + 0.2, back_w, fgettext("Back")),
  416. ("box[%f,%f;%f,0.8;#0000008C]"):format(
  417. back_w + 0.2, tabsize.height + 0.2, checkbox_w),
  418. ("checkbox[%f,%f;show_technical_names;%s;%s]"):format(
  419. back_w + 2*0.2, tabsize.height + 0.6,
  420. fgettext("Show technical names"), tostring(show_technical_names)),
  421. ("box[%f,%f;%f,0.8;#0000008C]"):format(
  422. back_w + 2*0.2 + checkbox_w, tabsize.height + 0.2, checkbox_w),
  423. ("checkbox[%f,%f;show_advanced;%s;%s]"):format(
  424. back_w + 3*0.2 + checkbox_w, tabsize.height + 0.6,
  425. fgettext("Show advanced settings"), tostring(show_advanced)),
  426. "field[0.25,0.25;", tostring(search_width), ",0.75;search_query;;",
  427. core.formspec_escape(dialogdata.query or ""), "]",
  428. "field_enter_after_edit[search_query;true]",
  429. "container[", tostring(search_width + 0.25), ", 0.25]",
  430. "image_button[0,0;0.75,0.75;", core.formspec_escape(defaulttexturedir .. "search.png"), ";search;]",
  431. "image_button[0.75,0;0.75,0.75;", core.formspec_escape(defaulttexturedir .. "clear.png"), ";search_clear;]",
  432. "tooltip[search;", fgettext("Search"), "]",
  433. "tooltip[search_clear;", fgettext("Clear"), "]",
  434. "container_end[]",
  435. "scroll_container[0.25,1.25;", tostring(left_pane_width), ",",
  436. tostring(tabsize.height - 1.5), ";leftscroll;vertical;0.1]",
  437. "style_type[button;border=false;bgcolor=#3333]",
  438. "style_type[button:hover;border=false;bgcolor=#6663]",
  439. }
  440. local y = 0
  441. local last_section = nil
  442. for _, other_page in ipairs(filtered_pages) do
  443. if other_page.section ~= last_section then
  444. fs[#fs + 1] = ("label[0.1,%f;%s]"):format(
  445. y + 0.41, core.colorize("#ff0", fgettext(other_page.section)))
  446. last_section = other_page.section
  447. y = y + 0.82
  448. end
  449. fs[#fs + 1] = ("box[0,%f;%f,0.8;%s]"):format(
  450. y, left_pane_width, other_page.id == page_id and "#467832FF" or "#3339")
  451. fs[#fs + 1] = ("button[0,%f;%f,0.8;page_%s;%s]")
  452. :format(y, left_pane_width, other_page.id, fgettext(other_page.title))
  453. y = y + 0.82
  454. end
  455. if #filtered_pages == 0 then
  456. fs[#fs + 1] = "label[0.1,0.41;"
  457. fs[#fs + 1] = fgettext("No results")
  458. fs[#fs + 1] = "]"
  459. end
  460. fs[#fs + 1] = "scroll_container_end[]"
  461. if y >= tabsize.height - 1.25 then
  462. fs[#fs + 1] = make_scrollbaroptions_for_scroll_container(tabsize.height - 1.5, y, 0.1)
  463. fs[#fs + 1] = ("scrollbar[%f,1.25;%f,%f;vertical;leftscroll;%f]"):format(
  464. left_pane_width + 0.25, scrollbar_w, tabsize.height - 1.5, dialogdata.leftscroll or 0)
  465. end
  466. fs[#fs + 1] = "style_type[button;border=;bgcolor=]"
  467. if not dialogdata.components then
  468. dialogdata.components = page and build_page_components(page) or {}
  469. end
  470. local right_pane_width = tabsize.width - left_pane_width - 0.375 - 2*scrollbar_w - 0.25
  471. fs[#fs + 1] = ("scroll_container[%f,0;%f,%f;rightscroll;vertical;0.1]"):format(
  472. tabsize.width - right_pane_width - scrollbar_w, right_pane_width, tabsize.height)
  473. y = 0.25
  474. for i, comp in ipairs(dialogdata.components) do
  475. fs[#fs + 1] = ("container[0,%f]"):format(y)
  476. local avail_w = right_pane_width - 0.25
  477. if not comp.full_width then
  478. avail_w = avail_w - 1.4
  479. end
  480. if comp.max_w then
  481. avail_w = math.min(avail_w, comp.max_w)
  482. end
  483. local comp_fs, used_h = comp:get_formspec(avail_w)
  484. fs[#fs + 1] = comp_fs
  485. fs[#fs + 1] = "style_type[image_button;border=false;padding=]"
  486. local show_reset = comp.resettable and comp.setting
  487. local show_info = comp.info_text and comp.info_text ~= ""
  488. if show_reset or show_info then
  489. -- ensure there's enough space for reset/info
  490. used_h = math.max(used_h, 0.5)
  491. end
  492. local info_reset_y = used_h / 2 - 0.25
  493. if show_reset then
  494. local default = comp.setting.default
  495. local reset_tooltip = default and
  496. fgettext("Reset setting to default ($1)", tostring(default)) or
  497. fgettext("Reset setting to default")
  498. fs[#fs + 1] = ("image_button[%f,%f;0.5,0.5;%s;%s;]"):format(
  499. right_pane_width - 1.4, info_reset_y, reset_icon_path, "reset_" .. i)
  500. fs[#fs + 1] = ("tooltip[%s;%s]"):format("reset_" .. i, reset_tooltip)
  501. end
  502. if show_info then
  503. local info_x = right_pane_width - 0.75
  504. fs[#fs + 1] = ("image[%f,%f;0.5,0.5;%s]"):format(info_x, info_reset_y, info_icon_path)
  505. fs[#fs + 1] = ("tooltip[%f,%f;0.5,0.5;%s]"):format(info_x, info_reset_y, fgettext(comp.info_text))
  506. end
  507. fs[#fs + 1] = "style_type[image_button;border=;padding=]"
  508. fs[#fs + 1] = "container_end[]"
  509. if used_h > 0 then
  510. y = y + used_h + 0.25
  511. end
  512. end
  513. fs[#fs + 1] = "scroll_container_end[]"
  514. if y >= tabsize.height then
  515. fs[#fs + 1] = make_scrollbaroptions_for_scroll_container(tabsize.height, y + 0.375, 0.1)
  516. fs[#fs + 1] = ("scrollbar[%f,0;%f,%f;vertical;rightscroll;%f]"):format(
  517. tabsize.width - scrollbar_w, scrollbar_w, tabsize.height, dialogdata.rightscroll or 0)
  518. end
  519. return table.concat(fs, "")
  520. end
  521. local function buttonhandler(this, fields)
  522. local dialogdata = this.data
  523. dialogdata.leftscroll = core.explode_scrollbar_event(fields.leftscroll).value or dialogdata.leftscroll
  524. dialogdata.rightscroll = core.explode_scrollbar_event(fields.rightscroll).value or dialogdata.rightscroll
  525. dialogdata.query = fields.search_query
  526. if fields.back then
  527. this:delete()
  528. return true
  529. end
  530. if fields.show_technical_names ~= nil then
  531. local value = core.is_yes(fields.show_technical_names)
  532. core.settings:set_bool("show_technical_names", value)
  533. return true
  534. end
  535. if fields.show_advanced ~= nil then
  536. local value = core.is_yes(fields.show_advanced)
  537. core.settings:set_bool("show_advanced", value)
  538. local suggested_page_id = update_filtered_pages(dialogdata.query)
  539. if not filtered_page_by_id[dialogdata.page_id] then
  540. dialogdata.components = nil
  541. dialogdata.leftscroll = 0
  542. dialogdata.rightscroll = 0
  543. dialogdata.page_id = suggested_page_id
  544. end
  545. return true
  546. end
  547. if fields.search or fields.key_enter_field == "search_query" then
  548. dialogdata.components = nil
  549. dialogdata.leftscroll = 0
  550. dialogdata.rightscroll = 0
  551. dialogdata.page_id = update_filtered_pages(dialogdata.query)
  552. return true
  553. end
  554. if fields.search_clear then
  555. dialogdata.query = ""
  556. dialogdata.components = nil
  557. dialogdata.leftscroll = 0
  558. dialogdata.rightscroll = 0
  559. dialogdata.page_id = update_filtered_pages("")
  560. return true
  561. end
  562. for _, page in ipairs(all_pages) do
  563. if fields["page_" .. page.id] then
  564. dialogdata.page_id = page.id
  565. dialogdata.components = nil
  566. dialogdata.rightscroll = 0
  567. return true
  568. end
  569. end
  570. for i, comp in ipairs(dialogdata.components) do
  571. if comp.on_submit and comp:on_submit(fields, this) then
  572. -- Clear components so they regenerate
  573. dialogdata.components = nil
  574. return true
  575. end
  576. if comp.setting and fields["reset_" .. i] then
  577. core.settings:remove(comp.setting.name)
  578. -- Clear components so they regenerate
  579. dialogdata.components = nil
  580. return true
  581. end
  582. end
  583. return false
  584. end
  585. local function eventhandler(event)
  586. if event == "DialogShow" then
  587. -- Don't show the "MINETEST" header behind the dialog.
  588. mm_game_theme.set_engine(true)
  589. return true
  590. end
  591. return false
  592. end
  593. function create_settings_dlg()
  594. local dlg = dialog_create("dlg_settings", get_formspec, buttonhandler, eventhandler)
  595. dlg.data.page_id = update_filtered_pages("")
  596. return dlg
  597. end