diff --git a/API.md b/API.md index 44c0b52..b65b208 100644 --- a/API.md +++ b/API.md @@ -43,6 +43,21 @@ - `mtos:set_theme(theme)`- Activate theme - `mtos:save()` - Store all app-data to nodemeta. Called mostly internally so no explicit call necessary - `mtos:pass_to_app(method, reshow, sender, ...)` - call custom "method" on app object. Used internally. Reshow means update formspec after update +- `mtos:select_file_dialog(param)` - call the select file dialog ('os:select_file') +``` + if fields.load then + mtos:select_file_dialog({ + mode = 'open', -- open/select or save mode + allowed_disks = {'hdd', 'removable'}, -- disks shown in disk overview ('ram', 'hdd', 'removable', 'cloud' or 'system') + selected_disk_name = data.selected_disk_name, -- Start selection on disk + selected_file_name = data.selected_file_name, -- Start selection with file + store_name = store_area, -- The storage_name used for fliles (Sample 'stickynote:files') + prefix = 'open_', -- Prefix for return files + }) + elseif fields.open_selected_disk and fields.open_selected_file then + data.selected_disk_name = fields.open_selected_disk -- Selected disk (prefix 'open_' is used) + data.selected_file_name = fields.open_selected_file -- Selected file (prefix 'open_' is used) +``` ### Operating system attributes `mtos.pos` - Computers position vector @@ -77,7 +92,7 @@ same as register_app, but the view flag is set. app_name and app_icon not necess ### App Object `local app = mtos:get_app(appname)` - Give the app object internal_shortname, connected to given mtos. Not necessary in formspec_func or receive_fields_func because given trough interface -- `app:back_app()` - Go back to previous app/view +- `app:back_app(fields, sender)` - Go back to previous app/view. Trough fields/sender additional data can be sent to the previous app trough receive_fields_func - `app:exit_app()` - Delete call stack and return to launcher @@ -110,12 +125,12 @@ Can be used for non-data and/or system tasks. For usual data store please use th - `bdev:get_ram_disk()` ram store - a table with all app-related storage partitions - `bdev:get_hard_disk()` hdd store - a table with all app-related storage partitions, if hard disk capatibility exists - `bdev:get_removable_disk()` removable data object (drive) -- `bdev:get_cloud_disk(store_name)` - Get named cloud storage +- `bdev:get_cloud_disk(storage_name)` - Get named cloud storage - `bdev:sync()` - Write/store all opened and maybe changed data ### Storage methods - `get_boot_disk()` - Check which device can be booted. possible return value is "hdd" or "removable" -- `get_app_storage(disk_type, store_name)` - Get data storage table to be used in apps. +- `get_app_storage(disk_type, storage_name)` - Get data storage table to be used in apps. - disk_type can be 'ram', 'hdd', 'removable', 'cloud' or 'system'. System is eather hdd or removable storage depending on booted device - store_name is usually the app name. 'os' is reserved for System related saves diff --git a/app_fw.lua b/app_fw.lua index 6bc7351..2e26b97 100644 --- a/app_fw.lua +++ b/app_fw.lua @@ -48,8 +48,11 @@ function app_class:receive_data(method, reshow, sender, ...) end -- Back to previous app in stack -function app_class:back_app() +function app_class:back_app(fields, sender) self.os.sysram.current_app = self.os:appstack_pop() + if fields then + self.os:pass_to_app('receive_fields_func', true, sender, fields) + end self.os:set_app(self.os.sysram.current_app) end diff --git a/apps/os_dialogs_app.lua b/apps/os_dialogs_app.lua new file mode 100644 index 0000000..782fb3e --- /dev/null +++ b/apps/os_dialogs_app.lua @@ -0,0 +1,160 @@ +-- Tool to get data +local function get_file(key, value) + if not value then + return { name = key } + elseif type(value) == 'string' then + return { name = key, content = value } + else + return { + name = key, +-- content = value.content or value, + owner = value.owner, + ctime = value.ctime, + } + end +end + + + +laptop.register_view('os:select_file', { + formspec_func = function(app, mtos) + local param = mtos.bdev:get_app_storage('ram', 'os:select_file').param + local allowed_disks = param.allowed_disks or { 'system' } + local selected_disk + if param.selected_disk_name then + selected_disk = mtos.bdev:get_app_storage(param.selected_disk_name, param.store_name) + end + + -- Get all available storage and check the storage_list + local storage_list = {} + for idx, disk in ipairs(allowed_disks) do + local dev_exists = mtos.bdev:get_app_storage(disk, param.store_name) + if dev_exists then + if not selected_disk then + selected_disk = dev_exists + param.selected_disk_name = disk + end + table.insert(storage_list, disk) + end + end + + -- Get sorted files list + param.files_list = {} + if selected_disk then + for key, value in pairs(selected_disk) do + table.insert(param.files_list, get_file(key, value)) + end + end + table.sort(param.files_list, function(a,b) return a.name 1 then + formspec = formspec..',' + end + formspec = formspec..file.name..','..(file.owner or '')..',' + if file.ctime then + formspec = formspec..os.date("%c", file.ctime) + end + if file.name == param.selected_file_name then + selected_idx = idx + end + end + formspec = formspec .. ";"..selected_idx.."]" + + -- Buttons + if param.mode == 'save' then + formspec = formspec .. "background[1.5,8.8;11,1.2;"..mtos.theme.contrast_bg.."]" .. + 'label[1.6,9.1;File name:]'.."field[3.2,9.3;5.5,0.8;filename;;"..(param.selected_file_name or "").."]" + else + formspec = formspec .. mtos.theme:get_label('1.5, 9.3', "Selected file: "..(param.selected_file_name or "")) + end + if param.selected_file_name and param.selected_file_name ~= "" and + selected_disk and selected_disk[param.selected_file_name] then + formspec = formspec .. mtos.theme:get_button('10.2,8.9;1.5,1', 'minor', 'delete', 'Delete') + formspec = formspec .. mtos.theme:get_button('8.5,8.9;1.5,1', 'major', 'select', param.button_txt) + elseif param.mode == 'save' then + + formspec = formspec .. mtos.theme:get_button('8.5,8.9;1.5,1', 'major', 'select', param.button_txt) + :select_file_dialog(param) end + + return formspec + end, + +-- Input processing + receive_fields_func = function(app, mtos, sender, fields) + local st = mtos.bdev:get_app_storage('ram', 'os:select_file') + local param = st.param + + if fields.filename then + param.selected_file_name = fields.filename + end + + for field, value in pairs(fields) do + if field:sub(1,7) == 'disksel' then + param.selected_disk_name = field:sub(9,-1) + break + end + end + + if fields.mount then + mtos:set_app("removable") + + elseif fields.filesel then + local event = minetest.explode_table_event(fields.filesel) + if param.files_list[event.row] then + param.selected_file_name = param.files_list[event.row].name + end + + elseif fields.select and param.selected_file_name and param.selected_file_name ~= "" + and param.selected_disk_name and param.selected_disk_name ~= "" then + param.prefix = param.prefix or "" + local pass_fields = { + [param.prefix..'selected_disk'] = param.selected_disk_name, + [param.prefix..'selected_file'] = param.selected_file_name, + } + app:back_app(pass_fields, sender) + st.param = nil + elseif fields.delete and param.selected_disk_name and param.selected_file_name then + local store = mtos.bdev:get_app_storage(param.selected_disk_name, param.store_name) + if store then + store[param.selected_file_name] = nil + end + end + end +}) diff --git a/apps/stickynote_app.lua b/apps/stickynote_app.lua index 0de011f..b6bc9a7 100644 --- a/apps/stickynote_app.lua +++ b/apps/stickynote_app.lua @@ -1,16 +1,18 @@ +local store_area = 'stickynote:files' + laptop.register_app("stickynote", { app_name = "Notepad", app_icon = "laptop_notes_pad.png", - app_info = "Write notes in a text document.", + app_info = "Write notes in a text document", formspec_func = function(app, mtos) local data = mtos.bdev:get_app_storage('system', 'stickynote') data.files = data.files or {} - - if data.selected_file then - data.text = data.files[data.selected_file] - end data.text = data.text or "" + if data.selected_disk_name and data.selected_file_name then + app.app_info = app.app_info..' - Open File: '..data.selected_disk_name..' / '..data.selected_file_name + end + -- cache sorted files list if not data.fileslist_sorted then data.fileslist_sorted = {} @@ -20,31 +22,55 @@ laptop.register_app("stickynote", { table.sort(data.fileslist_sorted) end - local formspec = "background[0,0.35;15.2,8.2;"..mtos.theme.contrast_bg.."]".. - "textarea[0.35,0.35;15.08,9.5;text;;"..minetest.formspec_escape(data.text).."]".. - "dropdown[0,9;4,1;file_sel;" - - local selected_idx - for idx, filename in ipairs(data.fileslist_sorted) do - if idx > 1 then - formspec = formspec..',' - end - formspec = formspec .. filename - if data.selected_file and data.selected_file == filename then - selected_idx = idx - end - end - formspec = formspec .. ";"..(selected_idx or "").."]".. - mtos.theme:get_button('4,9;1.5,0.8', 'minor', 'load', 'Load', 'Load file').. - mtos.theme:get_button('5.7,9;1.5,0.8', 'minor', 'delete', 'Delete', 'Delete file').. - "field[7.6,9.3;4,0.8;filename;;"..(data.selected_file or "").."]".. - mtos.theme:get_button('11.6,9;1.5,0.8', 'minor', 'save', 'Save', 'Save file') + local formspec = "background[0,1.35;15.2,8.35;"..mtos.theme.contrast_bg.."]".. + "textarea[0.35,1.35;15.08,9.5;text;;"..minetest.formspec_escape(data.text).."]".. + mtos.theme:get_button('0,0.5;1.5,0.8', 'minor', 'clear', 'New', 'New file').. + mtos.theme:get_button('2,0.5;1.5,0.8', 'minor', 'load', 'Load', 'Load file').. + mtos.theme:get_button('4,0.5;1.5,0.8', 'minor', 'save', 'Save', 'Save file') return formspec end, receive_fields_func = function(app, mtos, sender, fields) + local data = mtos.bdev:get_app_storage('system', 'stickynote') if fields.text then - local data = mtos.bdev:get_app_storage('system', 'stickynote') data.text = fields.text end + + if fields.load then + mtos:select_file_dialog({ + mode = 'open', + allowed_disks = {'hdd', 'removable'}, + selected_disk_name = data.selected_disk_name, + selected_file_name = data.selected_file_name, + store_name = store_area, + prefix = 'open_', + }) + elseif fields.open_selected_disk and fields.open_selected_file then + data.selected_disk_name = fields.open_selected_disk + data.selected_file_name = fields.open_selected_file + local store = mtos.bdev:get_app_storage(data.selected_disk_name, store_area) + if store then + data.text = store[data.selected_file_name].content + end + elseif fields.save then + mtos:select_file_dialog({ + mode = 'save', + allowed_disks = {'hdd', 'removable'}, + selected_disk_name = data.selected_disk_name, + selected_file_name = data.selected_file_name, + store_name = store_area, + prefix = 'save_', + }) + elseif fields.save_selected_disk and fields.save_selected_file then + data.selected_disk_name = fields.save_selected_disk + data.selected_file_name = fields.save_selected_file + local store = mtos.bdev:get_app_storage(data.selected_disk_name, store_area) + if store then + store[data.selected_file_name] = { content = data.text, ctime = os.time(), owner = sender:get_player_name() } + end + elseif fields.clear then + data.selected_disk_name = nil + data.selected_file_name = nil + data.text = "" + end end }) diff --git a/node_fw.lua b/node_fw.lua index 04ea21f..8de566c 100644 --- a/node_fw.lua +++ b/node_fw.lua @@ -167,6 +167,8 @@ function laptop.register_hardware(name, hwdef) -- set node configuration for hooks local merged_hwdef = table.copy(hwdef) + merged_hwdef.name = name + merged_hwdef.nodename = nodename for k,v in pairs(hwdef.node_defs[variant]) do merged_hwdef[k] = v end diff --git a/os.lua b/os.lua index 61c4b71..2d3034e 100644 --- a/os.lua +++ b/os.lua @@ -141,6 +141,13 @@ function os_class:save() self.bdev:sync() end +-- Use parameter and launch the select_file dialog +-- Return values will be send as fields to the called app +function os_class:select_file_dialog(param) + local store = self.bdev:get_app_storage('ram', 'os:select_file') + store.param = param + self:set_app('os:select_file') +end ----------------------------------------------------- -- Get Operating system object -----------------------------------------------------