From a2ded8694e6ab215b989592fb35774ed5f4bf42e Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Wed, 6 Dec 2017 16:18:15 +0100 Subject: [PATCH 01/14] added mail app (working but not eye candy yet) --- apps/mail_app.lua | 169 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 apps/mail_app.lua diff --git a/apps/mail_app.lua b/apps/mail_app.lua new file mode 100644 index 0000000..c837ee4 --- /dev/null +++ b/apps/mail_app.lua @@ -0,0 +1,169 @@ +-- based on https://github.com/cheapie/mail + +laptop.register_app("mail", { + app_name = "Mail", + app_icon = "laptop_email_letter.png", + app_info = "Write mails to other players", + formspec_func = function(app, mtos) + local cloud = app:get_cloud_storage_ref("mail") + if not mtos.appdata.os.last_player then + mtos:set_app() -- no player. Back to launcher + return false + end + + if not cloud[mtos.appdata.os.last_player] then + mtos:set_app("mail:newplayer") + return false + end + local account = cloud[mtos.appdata.os.last_player] + + local formspec = + "label[4,-0.31;Welcome "..mtos.appdata.os.last_player.."]".. + "button[0,9;1.5,0.5;new;New Message]".. + "button[1.5,9;1.5,0.5;continue;Continue last mail]".. + "button[3,9;1.5,0.5;reply;Reply]".. + "button[4.5,9;1.5,0.5;forward;Forward]".. + "button[6,9;1.5,0.5;delete;Delete]".. + "button[8,9;1.5,0.5;markread;Mark Read]".. + "button[9.5,9;1.5,0.5;markunread;Mark Unread]".. + "textlist[0,0.5;7.5,8.2;message;" + + if account.inbox[1] then + for idx,message in ipairs(account.inbox) do + if idx ~= 1 then formspec = formspec .. "," end + if not message.is_read then + formspec = formspec .. "#FF8888" + end + formspec = formspec..os.date("%c", message.time) + formspec = formspec .. " : " .. minetest.formspec_escape(message.sender or "") .. " : " + if message.subject and message.subject ~= "" then + if string.len(message.subject) > 30 then + formspec = formspec .. minetest.formspec_escape(string.sub(message.subject,1,27)).. "..." + else + formspec = formspec .. minetest.formspec_escape(message.subject) + end + else + formspec = formspec .. "(No subject)" + end + end + formspec = formspec .. "]" + else + formspec = formspec .. "No mail :(]" + end + + if account.selectedmessage then + local sender = minetest.formspec_escape(account.selectedmessage.sender) or "" + local subject = minetest.formspec_escape(account.selectedmessage.subject) or "" + local body = minetest.formspec_escape(account.selectedmessage.body) or "" + formspec = formspec .. "label[8,0.5;From: "..sender.."]label[8,1;Subject: "..subject.."]textarea[8.25,1.5;7,8.35;body;;"..body.."]" + end + return formspec + end, + receive_fields_func = function(app, mtos, fields, sender) + if sender:get_player_name() ~= mtos.appdata.os.last_player then + mtos:set_app() -- wrong player. Back to launcher + return + end + + local cloud = app:get_cloud_storage_ref("mail") + local account = cloud[mtos.appdata.os.last_player] + local inbox = account.inbox + + if fields.message then + local event = minetest.explode_textlist_event(fields.message) + account.selectedmessage = inbox[event.index] + account.selectedindex = event.index + if event.type == "DCL" and account.selectedmessage then + account.selectedmessage.is_read = true + end + elseif fields.new then + account.newmessage = {} + mtos:set_app("mail:compose") + elseif fields.continue then + mtos:set_app("mail:compose") + elseif account.selectedindex then + if fields.delete then + table.remove(inbox, account.selectedindex) + elseif fields.reply then + account.newmessage = {} + account.newmessage.receiver = account.selectedmessage.sender + account.newmessage.subject = "Re: "..(account.selectedmessage.subject or "") + account.newmessage.body = "Type your reply here."..string.char(10)..string.char(10).."--Original message follows--"..string.char(10)..(account.selectedmessage.body or "") + mtos:set_app("mail:compose") + elseif fields.forward then + account.newmessage = {} + account.newmessage.subject = "Fw: "..(account.selectedmessage.subject or "") + account.newmessage.body = "Type your reply here."..string.char(10)..string.char(10).."--Original message follows--"..string.char(10)..(account.selectedmessage.body or "") + mtos:set_app("mail:compose") + elseif fields.markread then + account.selectedmessage.is_read = true + elseif fields.markunread then + account.selectedmessage.is_read = false + end + end + end +}) + +laptop.register_view("mail:newplayer", { + formspec_func = function(app, mtos) + return "label[1,3;No mail account for player "..mtos.appdata.os.last_player.. " found. Do you like to create a new account?]".. + "image_button[1,4;3,1;"..mtos.theme.major_button..';create;Create account]' + end, + receive_fields_func = function(app, mtos, fields, sender) + if sender:get_player_name() ~= mtos.appdata.os.last_player then + mtos:set_app() -- wrong player. Back to launcher + return + end + if fields.create then + local cloud = app:get_cloud_storage_ref("mail") + cloud[mtos.appdata.os.last_player] = { + inbox = {}, + sentbox = {} --TODO + } + app:back_app() + elseif fields.os_back then + app:exit_app() + end + end +}) + +-- Write new mail +laptop.register_view("mail:compose", { + formspec_func = function(app, mtos) + local cloud = app:get_cloud_storage_ref("mail") + local account = cloud[mtos.appdata.os.last_player] + account.newmessage = account.newmessage or {} + local message = account.newmessage + + local formspec = "field[0.25,1;4,1;receiver;To:;%s]field[0.25,2;4,1;subject;Subject:;%s]textarea[0.25,3;8,4;body;;%s]button[5,8;2,1;send;Send]" + formspec = string.format(formspec,minetest.formspec_escape(message.receiver or ""),minetest.formspec_escape(message.subject or ""),minetest.formspec_escape(message.body or "")) + if message.receiver and not cloud[message.receiver] then + formspec = formspec.."label[7,8;invalid receiver player]" + end + return formspec + end, + receive_fields_func = function(app, mtos, fields, sender) + if sender:get_player_name() ~= mtos.appdata.os.last_player then + mtos:set_app() -- wrong player. Back to launcher + return + end + + local cloud = app:get_cloud_storage_ref("mail") + local account = cloud[mtos.appdata.os.last_player] + account.newmessage = account.newmessage or {} + local message = account.newmessage + + message.receiver = fields.receiver or message.receiver + message.sender = mtos.appdata.os.last_player + message.time = os.time() + message.subject = fields.subject or message.subject + message.body = fields.body or message.body + + if fields.send and message.receiver and cloud[message.receiver] then + table.insert(cloud[message.receiver].inbox, message) + table.insert(account.sentbox, table.copy(message)) + account.newmessage = nil + app:back_app() + end + end +}) From ba2790ed6cc49f46b42e1ae7fc227a91a300f6f6 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Fri, 8 Dec 2017 22:07:23 +0100 Subject: [PATCH 02/14] addjust theme name --- nodes.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes.lua b/nodes.lua index dce14a9..4189e01 100644 --- a/nodes.lua +++ b/nodes.lua @@ -73,7 +73,7 @@ laptop.register_hardware("laptop:cube", { description = "CUBE PC", infotext = "CUBE PC", sequence = { "off", "on"}, - custom_theme = "red", + custom_theme = "Red", node_defs = { ["on"] = { hw_state = "power_on", From 5d55b273c749d7ba709b794a2103c76fc888102c Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sat, 9 Dec 2017 08:54:46 +0100 Subject: [PATCH 03/14] renamed os variables to mtos to avoid confusions with system os global --- API.md | 34 ++++++++++++++++---------------- apps/launcher_app.lua | 27 +++++++++++++------------ apps/launcher_settings_app.lua | 10 +++++----- demo_apps.lua | 16 +++++++-------- node_fw.lua | 36 +++++++++++++++++----------------- 5 files changed, 62 insertions(+), 61 deletions(-) diff --git a/API.md b/API.md index 8fbca7d..5f9464c 100644 --- a/API.md +++ b/API.md @@ -21,26 +21,26 @@ - `laptop.os_get(pos)` - Get an OS object. Usefull in on_construct or on_punch to initialize or do anything with OS - Needed in on_receive_fields to be able to call os:receive_fields(fields, sender) for interactive apps + Needed in on_receive_fields to be able to call mtos:receive_fields(fields, sender) for interactive apps - `laptop.after_place_node` / `laptop.after_dig_node` - (optional) can be used directly for node definition. Move laptop apps data to ItemStack if digged and restored back if placed again. So you can take along your laptop. Note: you need to set `stack_max = 1` because the data can be stored per stack only, not per item. ## Operating system calls Usable from node functions, from apps or outsite -`local os = laptop.os_get(pos)` - Get the Operating system object. pos is the node position +`local mtos = laptop.os_get(pos)` - Get the Operating system object. pos is the node position -- `os:power_on(new_node_name)` - Activate the app "launcher" and if given swap node to new_node_name -- `os:resume(new_node_name)` - Restore the last running app after power_off. if given swap node to new_node_name -- `os:power_off(new_node_name)` - Remove the formspec and if given swap node to new_node_name -- `os:swap_node(new_node_name)`- Swap the node only without any changes on OS -- `os:set_infotext(infotext)` - Set the mouseover infotext for laptop node -- `os:save()` - Store all app-data to nodemeta. Called mostly internally so no explicit call necessary -- `os:get_app(appname)`- Get the app instance -- `os:set_app(appname)` - Start/Enable/navigate to appname. If no appname given the launcher is called -- `os:receive_fields(fields, sender)` - Should be called from node.on_receive_fields to get the apps interactive -- `os:get_theme(theme)`- Get theme data current or requested (theme parameter is optional) -- `os:set_theme(theme)`- Activate theme +- `mtos:power_on(new_node_name)` - Activate the app "launcher" and if given swap node to new_node_name +- `mtos:resume(new_node_name)` - Restore the last running app after power_off. if given swap node to new_node_name +- `mtos:power_off(new_node_name)` - Remove the formspec and if given swap node to new_node_name +- `mtos:swap_node(new_node_name)`- Swap the node only without any changes on OS +- `mtos:set_infotext(infotext)` - Set the mouseover infotext for laptop node +- `mtos:save()` - Store all app-data to nodemeta. Called mostly internally so no explicit call necessary +- `mtos:get_app(appname)`- Get the app instance +- `mtos:set_app(appname)` - Start/Enable/navigate to appname. If no appname given the launcher is called +- `mtos:receive_fields(fields, sender)` - Should be called from node.on_receive_fields to get the apps interactive +- `mtos:get_theme(theme)`- Get theme data current or requested (theme parameter is optional) +- `mtos:set_theme(theme)`- Activate theme ## App Definition @@ -50,14 +50,14 @@ Usable from node functions, from apps or outsite - `app_info` - Short app info visible in launcher tooltip - `fullscreen` - (boolean) Do not add app-background and window buttons - `view` - (boolean) The definition is a view. That means the app/view is not visible in launcher -- `formspec_func(app, os)` - Function, should return the app formspec (mandatory) During definition the "app" and the "os" are available -- `appwindow_formspec_func(launcher_app, app, os)`- Only custom launcher app: App background / Window decorations and buttons -- `receive_fields_func(app, os, fields, sender)` Function for input processing. The "app" and the "os" are available inside the call +- `formspec_func(app, mtos)` - Function, should return the app formspec (mandatory) During definition the "app" and the "mtos" are available +- `appwindow_formspec_func(launcher_app, app, mtos)`- Only custom launcher app: App background / Window decorations and buttons +- `receive_fields_func(app, mtos, fields, sender)` Function for input processing. The "app" and the "mtos" are available inside the call `laptop.register_view(internal_shortname, { definitiontable })` - add a new app or view same as register_app, but the view flag is set. app_name and app_icon not necessary ## App Object -`local app = os:get_app(appname)` - Give the app object internal_shortname, connected to given os. Not necessary in formspec_func or receive_fields_func because given trough interface +`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 - `data = app:get_storage_ref(appname)` - Returns a "persitant" data table from nodemeta (=hdd). The data in this table is not lost between formspec_func, receive_fields_func, apps-switch or on/off. Appname is optional to get data from other app - `data = app:get_cloud_storage_ref(appname)` - Returns a persistant table from modmeta (=internet) - `app:back_app() - Go back to previous app/view diff --git a/apps/launcher_app.lua b/apps/launcher_app.lua index ef47074..d8e22bb 100644 --- a/apps/launcher_app.lua +++ b/apps/launcher_app.lua @@ -2,13 +2,13 @@ laptop.register_app("launcher", { -- app_name = "Main launcher", -- not in launcher list fullscreen = true, - formspec_func = function(launcher_app, os) + formspec_func = function(launcher_app, mtos) local c_row_count = 4 local i = 0 local out = "size[15,10]" - if os.theme.launcher_bg then - out = out..'background[15,10;0,0;'..os.theme.launcher_bg..';true]' + if mtos.theme.launcher_bg then + out = out..'background[15,10;0,0;'..mtos.theme.launcher_bg..';true]' end local appslist_sorted = {} for name, def in pairs(laptop.apps) do @@ -20,34 +20,35 @@ laptop.register_app("launcher", { for i, e in ipairs(appslist_sorted) do local x = math.floor((i-1) / c_row_count)*2 + 1 local y = ((i-1) % c_row_count)*2 + 1 - out = out .. 'image_button['..x..','..y..';1,1;'..os.theme.app_button..'^'..(e.def.app_icon or 'logo.png')..';'..e.name..';]'.. + out = out .. 'image_button['..x..','..y..';1,1;'..mtos.theme.app_button..'^'..(e.def.app_icon or 'logo.png')..';'..e.name..';]'.. 'label['..(x-0.3)..','..(y+1)..';'..e.def.app_name..']'.. 'tooltip['..e.name..';'..(e.def.app_info or e.name)..']' --;;]' end + out = out..'label[12,9.8;'..tostring(os.date("%c"))..']' return out end, - appwindow_formspec_func = function(launcher_app, app, os) + appwindow_formspec_func = function(launcher_app, app, mtos) local formspec = 'size[15,10]' - if os.theme.app_bg then - formspec = formspec..'background[0,0;15,10;'..os.theme.app_bg..';true]' + if mtos.theme.app_bg then + formspec = formspec..'background[0,0;15,10;'..mtos.theme.app_bg..';true]' end - if #os.appdata.os.stack > 0 then - formspec = formspec..'image_button[-0.29,-0.31;1.09,0.61;'..os.theme.back_button..';os_back;<]' --TODO: if stack exists + if #mtos.appdata.os.stack > 0 then + formspec = formspec..'image_button[-0.29,-0.31;1.09,0.61;'..mtos.theme.back_button..';os_back;<]' --TODO: if stack exists end if app.app_info then - if #os.appdata.os.stack > 0 then + if #mtos.appdata.os.stack > 0 then formspec = formspec.."label[0.8,-0.29;"..app.app_info.."]" else formspec = formspec.."label[-0.1,-0.29;"..app.app_info.."]" end end - formspec = formspec..'image_button[14.2,-0.31;1.09,0.61;'..os.theme.exit_button..';os_exit;X]' + formspec = formspec..'image_button[14.2,-0.31;1.09,0.61;'..mtos.theme.exit_button..';os_exit;X]' return formspec end, - receive_fields_func = function(launcher_app, os, fields, sender) + receive_fields_func = function(launcher_app, mtos, fields, sender) for name, descr in pairs(fields) do if laptop.apps[name] then - os:set_app(name) + mtos:set_app(name) break end end diff --git a/apps/launcher_settings_app.lua b/apps/launcher_settings_app.lua index f0ebfb0..8170783 100644 --- a/apps/launcher_settings_app.lua +++ b/apps/launcher_settings_app.lua @@ -12,12 +12,12 @@ laptop.register_app("launcher_settings", { app_icon = "laptop_setting_wrench.png", app_info = "Change the computer's settings.", - formspec_func = function(app, os) + formspec_func = function(app, mtos) local settings_data = app:get_storage_ref() -- Change background setting - local current_theme_name = settings_data.selected_theme or os:get_theme().name or "default" - local current_theme = os:get_theme(current_theme_name) + local current_theme_name = settings_data.selected_theme or mtos:get_theme().name or "default" + local current_theme = mtos:get_theme(current_theme_name) local current_idx local formspec = "label[0,0.5;Select theme]" @@ -46,7 +46,7 @@ laptop.register_app("launcher_settings", { return formspec end, - receive_fields_func = function(app, os, fields, sender) + receive_fields_func = function(app, mtos, fields, sender) local settings_data = app:get_storage_ref() if fields.sel_theme then @@ -56,7 +56,7 @@ laptop.register_app("launcher_settings", { end if fields.theme_apply and settings_data.selected_theme then - os:set_theme(settings_data.selected_theme) + mtos:set_theme(settings_data.selected_theme) settings_data.selected_theme = nil app:exit_app() end diff --git a/demo_apps.lua b/demo_apps.lua index 7b76e74..a33f888 100644 --- a/demo_apps.lua +++ b/demo_apps.lua @@ -3,36 +3,36 @@ laptop.register_app("demo1", { app_name = "Demo App", app_icon = "laptop_setting_wrench.png", app_info = "The first and simple demo app", - formspec_func = function(app, os) - return 'image_button[5,5;3,1;'..os.theme.major_button..';next;Second screen]' + formspec_func = function(app, mtos) + return 'image_button[5,5;3,1;'..mtos.theme.major_button..';next;Second screen]' end, - receive_fields_func = function(app, os, fields, sender) + receive_fields_func = function(app, mtos, fields, sender) if fields.next then - os:set_app("demo1_view2") + mtos:set_app("demo1_view2") end end }) laptop.register_view("demo1_view2", { app_info = "Second screen in Demo App 1", - formspec_func = function(app, os) + formspec_func = function(app, mtos) return "label[1,5;Use the framework buttons to navigate back or cancel]" end, - receive_fields_func = function(app, os, fields, sender) + receive_fields_func = function(app, mtos, fields, sender) end }) laptop.register_app("demo2", { app_name = "Demo App 2", - formspec_func = function(app, os) + formspec_func = function(app, mtos) local data = app:get_storage_ref() data.counter = data.counter or 1 return 'button[3,1;5,1;count;Click: '..data.counter..']'.. 'button[3,3;5,1;back;Back to launcher]' end, - receive_fields_func = function(app, os, fields, sender) + receive_fields_func = function(app, mtos, fields, sender) if fields.count then local data = app:get_storage_ref() data.counter = data.counter + 1 diff --git a/node_fw.lua b/node_fw.lua index 451e07a..291052d 100644 --- a/node_fw.lua +++ b/node_fw.lua @@ -4,12 +4,12 @@ laptop.node_config = {} local function after_place_node(pos, placer, itemstack, pointed_thing) local appdata = minetest.deserialize(itemstack:get_meta():get_string("laptop_appdata")) if appdata then - local os = laptop.os_get(pos) - os.appdata = appdata - os.appdata.launcher = os.appdata.launcher or {} - os.appdata.os = os.appdata.os or {} - os.appdata.os.stack = os.appdata.os.stack or {} - os:save() + local mtos = laptop.os_get(pos) + mtos.appdata = appdata + mtos.appdata.launcher = mtos.appdata.launcher or {} + mtos.appdata.os = mtos.appdata.os or {} + mtos.appdata.os.stack = mtos.appdata.os.stack or {} + mtos:save() end end @@ -30,38 +30,38 @@ local function after_dig_node(pos, oldnode, oldmetadata, digger) end local function on_construct(pos) - local os = laptop.os_get(pos) + local mtos = laptop.os_get(pos) local node = minetest.get_node(pos) local hwdef = laptop.node_config[node.name] if hwdef.custom_theme then -- initial only - os:set_theme(hwdef.custom_theme) + mtos:set_theme(hwdef.custom_theme) end if hwdef.hw_state then - os[hwdef.hw_state](os) + mtos[hwdef.hw_state](mtos) else - os:power_off() + mtos:power_off() end - os:set_infotext(hwdef.hw_infotext) + mtos:set_infotext(hwdef.hw_infotext) end local function on_punch(pos, node, puncher) - local os = laptop.os_get(pos) + local mtos = laptop.os_get(pos) local hwdef = laptop.node_config[node.name] if hwdef.next_node then local hwdef_next = laptop.node_config[hwdef.next_node] if hwdef_next.hw_state then - os[hwdef_next.hw_state](os, hwdef.next_node) + mtos[hwdef_next.hw_state](mtos, hwdef.next_node) else - os:swap_node(hwdef.next_node) - os:save() + mtos:swap_node(hwdef.next_node) + mtos:save() end - os:set_infotext(hwdef_next.hw_infotext) + mtos:set_infotext(hwdef_next.hw_infotext) end end local function on_receive_fields(pos, formname, fields, sender) - local os = laptop.os_get(pos) - os:receive_fields(fields, sender) + local mtos = laptop.os_get(pos) + mtos:receive_fields(fields, sender) end function laptop.register_hardware(name, hwdef) From 63bb4262d71b1087d6cc5f2e179aaaa6b84cea03 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sun, 10 Dec 2017 18:52:08 +0100 Subject: [PATCH 04/14] moved textures to laptop_* namespace --- textures/{email_edit.png => laptop_email_edit.png} | Bin .../{email_forward.png => laptop_email_forward.png} | Bin textures/{email_new.png => laptop_email_new.png} | Bin .../{email_reply.png => laptop_email_reply.png} | Bin .../{email_trash.png => laptop_email_trash.png} | Bin textures/{mail.png => laptop_mail.png} | Bin textures/{mail_read.png => laptop_mail_read.png} | Bin 7 files changed, 0 insertions(+), 0 deletions(-) rename textures/{email_edit.png => laptop_email_edit.png} (100%) rename textures/{email_forward.png => laptop_email_forward.png} (100%) rename textures/{email_new.png => laptop_email_new.png} (100%) rename textures/{email_reply.png => laptop_email_reply.png} (100%) rename textures/{email_trash.png => laptop_email_trash.png} (100%) rename textures/{mail.png => laptop_mail.png} (100%) rename textures/{mail_read.png => laptop_mail_read.png} (100%) diff --git a/textures/email_edit.png b/textures/laptop_email_edit.png similarity index 100% rename from textures/email_edit.png rename to textures/laptop_email_edit.png diff --git a/textures/email_forward.png b/textures/laptop_email_forward.png similarity index 100% rename from textures/email_forward.png rename to textures/laptop_email_forward.png diff --git a/textures/email_new.png b/textures/laptop_email_new.png similarity index 100% rename from textures/email_new.png rename to textures/laptop_email_new.png diff --git a/textures/email_reply.png b/textures/laptop_email_reply.png similarity index 100% rename from textures/email_reply.png rename to textures/laptop_email_reply.png diff --git a/textures/email_trash.png b/textures/laptop_email_trash.png similarity index 100% rename from textures/email_trash.png rename to textures/laptop_email_trash.png diff --git a/textures/mail.png b/textures/laptop_mail.png similarity index 100% rename from textures/mail.png rename to textures/laptop_mail.png diff --git a/textures/mail_read.png b/textures/laptop_mail_read.png similarity index 100% rename from textures/mail_read.png rename to textures/laptop_mail_read.png From 8657e6af84f22642fd29fa36550903722687402f Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sun, 10 Dec 2017 19:46:35 +0100 Subject: [PATCH 05/14] mail_app: switch to table formspec and fix reported bugs --- apps/mail_app.lua | 111 ++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 38 deletions(-) diff --git a/apps/mail_app.lua b/apps/mail_app.lua index c837ee4..4abc50f 100644 --- a/apps/mail_app.lua +++ b/apps/mail_app.lua @@ -16,42 +16,66 @@ laptop.register_app("mail", { return false end local account = cloud[mtos.appdata.os.last_player] - + local formspec = "label[4,-0.31;Welcome "..mtos.appdata.os.last_player.."]".. - "button[0,9;1.5,0.5;new;New Message]".. - "button[1.5,9;1.5,0.5;continue;Continue last mail]".. - "button[3,9;1.5,0.5;reply;Reply]".. + +-- "textlist[0,0.5;7.5,8.2;message;" + "tablecolumns[" .. + "image,align=center,1=laptop_mail.png,2=laptop_mail_read.png;".. --icon column + "color;".. -- subject and date color + "text;".. -- subject + "text,padding=1.5;".. -- sender + "text,padding=1.5,align=right]".. -- date + "table[0,0.5;7.5,8.2;message;" + + account.selected_inbox_index = nil + if account.inbox[1] then + for idx,message in ipairs(account.inbox) do + if idx > 1 then + formspec = formspec..',' + end + -- set read/unread status + if not message.is_read then + formspec = formspec .. "1,#FF8888," -- unread + else + formspec = formspec .. "2,#FFFFFF," -- read + end + + -- set subject + if not message.subject or message.subject == "" then + formspec = formspec .. "(No subject)," + elseif string.len(message.subject) > 30 then + formspec = formspec .. minetest.formspec_escape(string.sub(message.subject,1,27)) .. "...," + else + formspec = formspec .. minetest.formspec_escape(message.subject) .. "," + end + + -- set sender and date + formspec = formspec.. + minetest.formspec_escape(message.sender or "") ..",".. -- body + os.date("%c", message.time) -- timestamp + if account.selectedmessage and + message.sender == account.selectedmessage.sender and + message.subject == account.selectedmessage.subject and + message.time == account.selectedmessage.time and + message.body == account.selectedmessage.body then + account.selected_inbox_index = idx + end + end + formspec = formspec .. ";"..(account.selected_inbox_index or "").."]" + else + formspec = formspec .. ",,No mail :(]" + end + + formspec = formspec .. "button[0,9;1.5,0.5;new;New Message]".. + "button[1.5,9;1.5,0.5;continue;Continue last mail]" + if account.selectedmessage then + formspec = formspec .. "button[3,9;1.5,0.5;reply;Reply]".. "button[4.5,9;1.5,0.5;forward;Forward]".. "button[6,9;1.5,0.5;delete;Delete]".. "button[8,9;1.5,0.5;markread;Mark Read]".. - "button[9.5,9;1.5,0.5;markunread;Mark Unread]".. - "textlist[0,0.5;7.5,8.2;message;" - - if account.inbox[1] then - for idx,message in ipairs(account.inbox) do - if idx ~= 1 then formspec = formspec .. "," end - if not message.is_read then - formspec = formspec .. "#FF8888" - end - formspec = formspec..os.date("%c", message.time) - formspec = formspec .. " : " .. minetest.formspec_escape(message.sender or "") .. " : " - if message.subject and message.subject ~= "" then - if string.len(message.subject) > 30 then - formspec = formspec .. minetest.formspec_escape(string.sub(message.subject,1,27)).. "..." - else - formspec = formspec .. minetest.formspec_escape(message.subject) - end - else - formspec = formspec .. "(No subject)" - end - end - formspec = formspec .. "]" - else - formspec = formspec .. "No mail :(]" - end - - if account.selectedmessage then + "button[9.5,9;1.5,0.5;markunread;Mark Unread]" local sender = minetest.formspec_escape(account.selectedmessage.sender) or "" local subject = minetest.formspec_escape(account.selectedmessage.subject) or "" local body = minetest.formspec_escape(account.selectedmessage.body) or "" @@ -69,21 +93,32 @@ laptop.register_app("mail", { local account = cloud[mtos.appdata.os.last_player] local inbox = account.inbox + -- Set read status if 2 seconds selected + if account.selected_inbox_index and account.selectedmessage and + account.selected_inbox_timestamp and (account.selected_inbox_timestamp - os.time()) > 2 then + account.selectedmessage.is_read = true + end + if fields.message then - local event = minetest.explode_textlist_event(fields.message) - account.selectedmessage = inbox[event.index] - account.selectedindex = event.index - if event.type == "DCL" and account.selectedmessage then - account.selectedmessage.is_read = true + local event = minetest.explode_table_event(fields.message) + + account.selectedmessage = inbox[event.row] + if account.selectedmessage then + account.selected_inbox_index = event.row + account.selected_inbox_timestamp = os.time() + else + account.selected_inbox_index = nil + account.selected_inbox_timestamp = nil end + elseif fields.new then account.newmessage = {} mtos:set_app("mail:compose") elseif fields.continue then mtos:set_app("mail:compose") - elseif account.selectedindex then + elseif account.selected_inbox_index then if fields.delete then - table.remove(inbox, account.selectedindex) + table.remove(inbox, account.selected_inbox_index) elseif fields.reply then account.newmessage = {} account.newmessage.receiver = account.selectedmessage.sender From eeee55ea77eab9f637ee4538a8bf5868c3243fb0 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sun, 10 Dec 2017 20:18:46 +0100 Subject: [PATCH 06/14] mail_app: Formspec adjustments, usage for icons --- apps/mail_app.lua | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/apps/mail_app.lua b/apps/mail_app.lua index 4abc50f..b165d55 100644 --- a/apps/mail_app.lua +++ b/apps/mail_app.lua @@ -68,14 +68,21 @@ laptop.register_app("mail", { formspec = formspec .. ",,No mail :(]" end - formspec = formspec .. "button[0,9;1.5,0.5;new;New Message]".. - "button[1.5,9;1.5,0.5;continue;Continue last mail]" + formspec = formspec .. "image_button[0,9;1,1;laptop_email_new.png;new;]tooltip[new;New message]" + if account.newmessage then + formspec = formspec .. "image_button[1,9;1,1;laptop_email_edit.png;continue;]tooltip[continue;Continue last message]" + end + if account.selectedmessage then - formspec = formspec .. "button[3,9;1.5,0.5;reply;Reply]".. - "button[4.5,9;1.5,0.5;forward;Forward]".. - "button[6,9;1.5,0.5;delete;Delete]".. - "button[8,9;1.5,0.5;markread;Mark Read]".. - "button[9.5,9;1.5,0.5;markunread;Mark Unread]" + formspec = formspec .. + "image_button[2.7,9;1,1;laptop_email_reply.png;reply;]tooltip[reply;Reply]".. + "image_button[3.7,9;1,1;laptop_email_forward.png;forward;]tooltip[forward;Forward]".. + "image_button[4.7,9;1,1;laptop_email_trash.png;delete;]tooltip[delete;Delete]" + if not account.selectedmessage.is_read then + formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail_read.png;markread;]tooltip[markread;Mark message as read]" + else + formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail.png;markunread;]tooltip[markunread;Mark message as unread]" + end local sender = minetest.formspec_escape(account.selectedmessage.sender) or "" local subject = minetest.formspec_escape(account.selectedmessage.subject) or "" local body = minetest.formspec_escape(account.selectedmessage.body) or "" @@ -95,7 +102,7 @@ laptop.register_app("mail", { -- Set read status if 2 seconds selected if account.selected_inbox_index and account.selectedmessage and - account.selected_inbox_timestamp and (account.selected_inbox_timestamp - os.time()) > 2 then + account.selected_inbox_timestamp and (os.time() - account.selected_inbox_timestamp) > 1 then account.selectedmessage.is_read = true end @@ -108,7 +115,6 @@ laptop.register_app("mail", { account.selected_inbox_timestamp = os.time() else account.selected_inbox_index = nil - account.selected_inbox_timestamp = nil end elseif fields.new then @@ -119,6 +125,7 @@ laptop.register_app("mail", { elseif account.selected_inbox_index then if fields.delete then table.remove(inbox, account.selected_inbox_index) + account.selectedmessage = nil elseif fields.reply then account.newmessage = {} account.newmessage.receiver = account.selectedmessage.sender @@ -134,6 +141,7 @@ laptop.register_app("mail", { account.selectedmessage.is_read = true elseif fields.markunread then account.selectedmessage.is_read = false + account.selected_inbox_timestamp = nil -- Stop timer end end end From 8fb905cb1fac29ff72f71bfdd4e3e188dca7293c Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sun, 10 Dec 2017 21:27:48 +0100 Subject: [PATCH 07/14] mail_app: add sentbox. small adjustments --- apps/mail_app.lua | 104 +++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/apps/mail_app.lua b/apps/mail_app.lua index b165d55..3c7589b 100644 --- a/apps/mail_app.lua +++ b/apps/mail_app.lua @@ -16,11 +16,12 @@ laptop.register_app("mail", { return false end local account = cloud[mtos.appdata.os.last_player] + account.selected_box = account.selected_box or "inbox" + account.selected_index = nil -- will be new determinated by selectedmessage + local box = account[account.selected_box] -- inbox or outbox local formspec = "label[4,-0.31;Welcome "..mtos.appdata.os.last_player.."]".. - --- "textlist[0,0.5;7.5,8.2;message;" "tablecolumns[" .. "image,align=center,1=laptop_mail.png,2=laptop_mail_read.png;".. --icon column "color;".. -- subject and date color @@ -29,14 +30,15 @@ laptop.register_app("mail", { "text,padding=1.5,align=right]".. -- date "table[0,0.5;7.5,8.2;message;" - account.selected_inbox_index = nil - if account.inbox[1] then - for idx,message in ipairs(account.inbox) do + if box and box[1] then + for idx,message in ipairs(box) do if idx > 1 then formspec = formspec..',' end -- set read/unread status - if not message.is_read then + if account.selected_box == "sentbox" then + formspec = formspec .. "1,#88FF88," -- unread + elseif not message.is_read then formspec = formspec .. "1,#FF8888," -- unread else formspec = formspec .. "2,#FFFFFF," -- read @@ -51,42 +53,62 @@ laptop.register_app("mail", { formspec = formspec .. minetest.formspec_escape(message.subject) .. "," end - -- set sender and date - formspec = formspec.. - minetest.formspec_escape(message.sender or "") ..",".. -- body - os.date("%c", message.time) -- timestamp + -- set sender or receiver + if account.selected_box == "inbox" then + formspec = formspec..minetest.formspec_escape(message.sender or "") .."," -- body + else + formspec = formspec..minetest.formspec_escape(message.receiver or "") .."," -- body + end + + -- set date + formspec = formspec .. os.date("%c", message.time) -- timestamp + + -- handle marked line if account.selectedmessage and message.sender == account.selectedmessage.sender and message.subject == account.selectedmessage.subject and message.time == account.selectedmessage.time and message.body == account.selectedmessage.body then - account.selected_inbox_index = idx + account.selected_index = idx end end - formspec = formspec .. ";"..(account.selected_inbox_index or "").."]" + formspec = formspec .. ";"..(account.selected_index or "").."]" else formspec = formspec .. ",,No mail :(]" end - formspec = formspec .. "image_button[0,9;1,1;laptop_email_new.png;new;]tooltip[new;New message]" + -- toggle inbox/sentbox + if account.selected_box == "inbox" then + formspec = formspec .. "image_button[0,9;1.5,1;"..mtos.theme.minor_button..";switch_sentbox;Sentbox]tooltip[switch_sentbox;Show sent messages]" + else + formspec = formspec .. "image_button[0,9;1.5,1;"..mtos.theme.minor_button..";switch_inbox;Inbox]tooltip[switch_inbox;Show received messages]" + end + + formspec = formspec .. "image_button[1.7,9;1,1;laptop_email_new.png;new;]tooltip[new;New message]" if account.newmessage then - formspec = formspec .. "image_button[1,9;1,1;laptop_email_edit.png;continue;]tooltip[continue;Continue last message]" + formspec = formspec .. "image_button[2.7,9;1,1;laptop_email_edit.png;continue;]tooltip[continue;Continue last message]" end if account.selectedmessage then formspec = formspec .. - "image_button[2.7,9;1,1;laptop_email_reply.png;reply;]tooltip[reply;Reply]".. - "image_button[3.7,9;1,1;laptop_email_forward.png;forward;]tooltip[forward;Forward]".. - "image_button[4.7,9;1,1;laptop_email_trash.png;delete;]tooltip[delete;Delete]" - if not account.selectedmessage.is_read then - formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail_read.png;markread;]tooltip[markread;Mark message as read]" - else - formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail.png;markunread;]tooltip[markunread;Mark message as unread]" + "image_button[3.7,9;1,1;laptop_email_reply.png;reply;]tooltip[reply;Reply]".. + "image_button[4.7,9;1,1;laptop_email_forward.png;forward;]tooltip[forward;Forward]".. + "image_button[5.7,9;1,1;laptop_email_trash.png;delete;]tooltip[delete;Delete]" + if account.selected_box == "inbox" then + if not account.selectedmessage.is_read then + formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail_read.png;markread;]tooltip[markread;Mark message as read]" + else + formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail.png;markunread;]tooltip[markunread;Mark message as unread]" + end end - local sender = minetest.formspec_escape(account.selectedmessage.sender) or "" - local subject = minetest.formspec_escape(account.selectedmessage.subject) or "" - local body = minetest.formspec_escape(account.selectedmessage.body) or "" - formspec = formspec .. "label[8,0.5;From: "..sender.."]label[8,1;Subject: "..subject.."]textarea[8.25,1.5;7,8.35;body;;"..body.."]" + if account.selected_box == "inbox" then + formspec = formspec .. "label[8,0.5;From: "..(minetest.formspec_escape(account.selectedmessage.sender) or "").."]" + else + formspec = formspec .. "label[8,0.5;To: "..(minetest.formspec_escape(account.selectedmessage.receiver) or "").."]" + end + + formspec = formspec .. "label[8,1;Subject: "..(minetest.formspec_escape(account.selectedmessage.subject) or "").. + "]textarea[8.25,1.5;7,8.35;body;;"..(minetest.formspec_escape(account.selectedmessage.body) or "").."]" end return formspec end, @@ -98,33 +120,39 @@ laptop.register_app("mail", { local cloud = app:get_cloud_storage_ref("mail") local account = cloud[mtos.appdata.os.last_player] - local inbox = account.inbox + account.selected_box = account.selected_box or "inbox" + local box = account[account.selected_box] -- inbox or outbox -- Set read status if 2 seconds selected - if account.selected_inbox_index and account.selectedmessage and - account.selected_inbox_timestamp and (os.time() - account.selected_inbox_timestamp) > 1 then + if account.selected_index and account.selectedmessage and account.selected_box == "inbox" and + account.selected_timestamp and (os.time() - account.selected_timestamp) > 1 then account.selectedmessage.is_read = true end + -- process input if fields.message then local event = minetest.explode_table_event(fields.message) - - account.selectedmessage = inbox[event.row] + account.selectedmessage = box[event.row] if account.selectedmessage then - account.selected_inbox_index = event.row - account.selected_inbox_timestamp = os.time() + account.selected_index = event.row + account.selected_timestamp = os.time() else - account.selected_inbox_index = nil + account.selected_index = nil end - elseif fields.new then account.newmessage = {} mtos:set_app("mail:compose") elseif fields.continue then mtos:set_app("mail:compose") - elseif account.selected_inbox_index then + elseif fields.switch_sentbox then + account.selected_box = "sentbox" + account.selectedmessage = nil + elseif fields.switch_inbox then + account.selected_box = "inbox" + account.selectedmessage = nil + elseif account.selected_index then if fields.delete then - table.remove(inbox, account.selected_inbox_index) + table.remove(box, account.selected_index) account.selectedmessage = nil elseif fields.reply then account.newmessage = {} @@ -141,7 +169,7 @@ laptop.register_app("mail", { account.selectedmessage.is_read = true elseif fields.markunread then account.selectedmessage.is_read = false - account.selected_inbox_timestamp = nil -- Stop timer + account.selected_timestamp = nil -- Stop timer end end end @@ -161,7 +189,7 @@ laptop.register_view("mail:newplayer", { local cloud = app:get_cloud_storage_ref("mail") cloud[mtos.appdata.os.last_player] = { inbox = {}, - sentbox = {} --TODO + sentbox = {} } app:back_app() elseif fields.os_back then From 59245a419bf9432d18b614e7f8d97d07392bcfcd Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sun, 10 Dec 2017 22:17:44 +0100 Subject: [PATCH 08/14] launcher: take clock to button --- apps/launcher_app.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/launcher_app.lua b/apps/launcher_app.lua index d8e22bb..9ea68d9 100644 --- a/apps/launcher_app.lua +++ b/apps/launcher_app.lua @@ -24,7 +24,7 @@ laptop.register_app("launcher", { 'label['..(x-0.3)..','..(y+1)..';'..e.def.app_name..']'.. 'tooltip['..e.name..';'..(e.def.app_info or e.name)..']' --;;]' end - out = out..'label[12,9.8;'..tostring(os.date("%c"))..']' + out = out.."image_button[11,9.8;4,0.7;menu_bg.png;os_clock;"..tostring(os.date("%c")).."]" return out end, appwindow_formspec_func = function(launcher_app, app, mtos) From 2f3c4acca9be0081bc4e3aebc099345b0873b1ff Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sun, 10 Dec 2017 23:45:55 +0100 Subject: [PATCH 09/14] calculator app added --- apps/calculator_app.lua | 129 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 apps/calculator_app.lua diff --git a/apps/calculator_app.lua b/apps/calculator_app.lua new file mode 100644 index 0000000..b901ba8 --- /dev/null +++ b/apps/calculator_app.lua @@ -0,0 +1,129 @@ +laptop.register_app("calculator", { + app_name = "Calculator", + app_icon = "laptop_calculator.png", + app_info = "Calculate things", + formspec_func = function(app, mtos) + local data = app:get_storage_ref() + + if not data.tab then + data.tab = {} + end + if not data.tab[1] then + table.insert(data.tab, {}) + end + + local formspec = "tablecolumns[" .. + "text,align=right,padding=1.5,width=6;".. -- first value + "text,align=right,padding=1.5;".. -- operator + "text,align=right,padding=1.5,width=6]".. -- last value + "table[1,1;7,2;tab;" + + for idx,entry in ipairs(data.tab) do + if idx > 1 then + formspec = formspec..',' + end + formspec = formspec..(entry.var1 or "")..","..(entry.operator or "")..","..(entry.var2 or "0") + end + + formspec = formspec .. ";"..#data.tab.."]".. + "image_button[1,3;1,1;"..mtos.theme.minor_button..";number;1]".. + "image_button[2,3;1,1;"..mtos.theme.minor_button..";number;2]".. + "image_button[3,3;1,1;"..mtos.theme.minor_button..";number;3]".. + "image_button[1,4;1,1;"..mtos.theme.minor_button..";number;4]".. + "image_button[2,4;1,1;"..mtos.theme.minor_button..";number;5]".. + "image_button[3,4;1,1;"..mtos.theme.minor_button..";number;6]".. + "image_button[1,5;1,1;"..mtos.theme.minor_button..";number;7]".. + "image_button[2,5;1,1;"..mtos.theme.minor_button..";number;8]".. + "image_button[3,5;1,1;"..mtos.theme.minor_button..";number;9]".. + "image_button[1,6;1,1;"..mtos.theme.minor_button..";number;0]".. + "image_button[2,6;1,1;"..mtos.theme.minor_button..";number;.]".. + + "image_button[5,3;1,1;"..mtos.theme.minor_button..";operator;+]".. + "image_button[5,4;1,1;"..mtos.theme.minor_button..";operator;-]".. + "image_button[5,5;1,1;"..mtos.theme.minor_button..";operator;/]".. + "image_button[5,6;1,1;"..mtos.theme.minor_button..";operator;*]".. + "image_button[6,6;2,1;"..mtos.theme.minor_button..";operator;=]".. + + "image_button[6,3;2,1;"..mtos.theme.minor_button..";del_char;DEL-1]".. + "image_button[6,4;2,1;"..mtos.theme.minor_button..";del_line;DEL-L]".. + "image_button[6,5;2,1;"..mtos.theme.minor_button..";del_all;DEL-A]" + return formspec + end, + + receive_fields_func = function(app, mtos, fields, sender) + local data = app:get_storage_ref() + local entry = data.tab[#data.tab] + + if fields.number then + -- simple number entry + entry.var2 = (entry.var2 or "")..fields.number + elseif fields.del_char then + -- delete char + if entry.var2 and entry.var2 ~= "" then + -- remove char from current number + entry.var2 = entry.var2:sub(1, -2) + if entry.var2 == "" then + entry.var2 = nil + end + else + -- get previous number + if #data.tab > 1 then + -- go back to previous line if exists + table.remove(data.tab, #data.tab) + else + -- get from left site if first entry + entry.var2 = entry.var1 + entry.operator = nil + entry.var1 = nil + end + end + elseif fields.del_line then + -- just delete full number if exists + if entry.var2 and entry.var2 ~= "" then + entry.var2 = nil + else + -- go back to previous line and delete the full number if exists + table.remove(data.tab, #data.tab) + if #data.tab > 0 then + entry = data.tab[#data.tab] + entry.var2 = nil + end + end + elseif fields.del_all then + data.tab = nil + elseif fields.operator then + local entry = data.tab[#data.tab] + -- no previous operator + if not entry.operator then + if fields.operator == '=' then + table.insert(data.tab, {}) -- add empty line + elseif entry.var2 and entry.var2 ~= "" then + -- move to the left + entry.var1 = entry.var2 + entry.operator = fields.operator + entry.var2 = nil + end + + -- process previous operator + else + local result + if entry.operator == '+' then + result = tonumber(entry.var1) + tonumber(entry.var2) + elseif entry.operator == '-' then + result = tonumber(entry.var1) - tonumber(entry.var2) + elseif entry.operator == '/' then + result = tonumber(entry.var1) / tonumber(entry.var2) + elseif entry.operator == '*' then + result = tonumber(entry.var1) * tonumber(entry.var2) + elseif entry.operator == '=' then + result = tonumber(entry.var2) + end + if fields.operator == '=' then + table.insert(data.tab, {var2 = tostring(result)}) + else + table.insert(data.tab, {var1 = tostring(result), operator = fields.operator}) + end + end + end + end +}) From a7dc7887e60672ad2c836f388ca86f3500f364a5 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Mon, 11 Dec 2017 08:41:59 +0100 Subject: [PATCH 10/14] theming adjustments. Add methods for themed buttons and labels. Set default text to black for buttons and labels --- API.md | 5 ++++ apps/calculator_app.lua | 46 ++++++++++++++++++---------------- apps/launcher_app.lua | 2 +- apps/launcher_settings_app.lua | 5 ++-- apps/mail_app.lua | 34 ++++++++++++++----------- demo_apps.lua | 4 +-- os.lua | 11 +------- themes.lua | 29 ++++++++++++++++++++- 8 files changed, 83 insertions(+), 53 deletions(-) diff --git a/API.md b/API.md index 5f9464c..473305b 100644 --- a/API.md +++ b/API.md @@ -72,3 +72,8 @@ Definitiontable: - `exit_button` Exit button image - `major_button` Major (highlighted) button image - `minor_button` Minor button image + +## Theme methods +`function laptop.get_theme(theme_name)` +- `theme:get_button(area, prefix, code, text)` get a themed [prefix]_button in area 'x,y;w,h' with code an text +- `theme:get_label(pos, text)` get a themed label text starting at pos 'x,y' diff --git a/apps/calculator_app.lua b/apps/calculator_app.lua index b901ba8..5b2e5f5 100644 --- a/apps/calculator_app.lua +++ b/apps/calculator_app.lua @@ -16,7 +16,7 @@ laptop.register_app("calculator", { "text,align=right,padding=1.5,width=6;".. -- first value "text,align=right,padding=1.5;".. -- operator "text,align=right,padding=1.5,width=6]".. -- last value - "table[1,1;7,2;tab;" + "table[0.9,0.8;7,2;tab;" for idx,entry in ipairs(data.tab) do if idx > 1 then @@ -26,27 +26,27 @@ laptop.register_app("calculator", { end formspec = formspec .. ";"..#data.tab.."]".. - "image_button[1,3;1,1;"..mtos.theme.minor_button..";number;1]".. - "image_button[2,3;1,1;"..mtos.theme.minor_button..";number;2]".. - "image_button[3,3;1,1;"..mtos.theme.minor_button..";number;3]".. - "image_button[1,4;1,1;"..mtos.theme.minor_button..";number;4]".. - "image_button[2,4;1,1;"..mtos.theme.minor_button..";number;5]".. - "image_button[3,4;1,1;"..mtos.theme.minor_button..";number;6]".. - "image_button[1,5;1,1;"..mtos.theme.minor_button..";number;7]".. - "image_button[2,5;1,1;"..mtos.theme.minor_button..";number;8]".. - "image_button[3,5;1,1;"..mtos.theme.minor_button..";number;9]".. - "image_button[1,6;1,1;"..mtos.theme.minor_button..";number;0]".. - "image_button[2,6;1,1;"..mtos.theme.minor_button..";number;.]".. + mtos.theme:get_button('1,3;1,1', "minor", 'number', '1') .. + mtos.theme:get_button('2,3;1,1', "minor", 'number', '2') .. + mtos.theme:get_button('3,3;1,1', "minor", 'number', '3') .. + mtos.theme:get_button('1,4;1,1', "minor", 'number', '4') .. + mtos.theme:get_button('2,4;1,1', "minor", 'number', '5') .. + mtos.theme:get_button('3,4;1,1', "minor", 'number', '6') .. + mtos.theme:get_button('1,5;1,1', "minor", 'number', '7') .. + mtos.theme:get_button('2,5;1,1', "minor", 'number', '8') .. + mtos.theme:get_button('3,5;1,1', "minor", 'number', '9') .. + mtos.theme:get_button('1,6;1,1', "minor", 'number', '0') .. + mtos.theme:get_button('2,6;1,1', "minor", 'number', '.') .. - "image_button[5,3;1,1;"..mtos.theme.minor_button..";operator;+]".. - "image_button[5,4;1,1;"..mtos.theme.minor_button..";operator;-]".. - "image_button[5,5;1,1;"..mtos.theme.minor_button..";operator;/]".. - "image_button[5,6;1,1;"..mtos.theme.minor_button..";operator;*]".. - "image_button[6,6;2,1;"..mtos.theme.minor_button..";operator;=]".. + mtos.theme:get_button('5,3;1,1', "minor", 'operator', '+') .. + mtos.theme:get_button('5,4;1,1', "minor", 'operator', '-') .. + mtos.theme:get_button('5,5;1,1', "minor", 'operator', '/') .. + mtos.theme:get_button('5,6;1,1', "minor", 'operator', '*') .. + mtos.theme:get_button('6,6;2,1', "minor", 'operator', '=') .. - "image_button[6,3;2,1;"..mtos.theme.minor_button..";del_char;DEL-1]".. - "image_button[6,4;2,1;"..mtos.theme.minor_button..";del_line;DEL-L]".. - "image_button[6,5;2,1;"..mtos.theme.minor_button..";del_all;DEL-A]" + mtos.theme:get_button('6,3;2,1', "minor", 'del_char', 'DEL-1') .. + mtos.theme:get_button('6,4;2,1', "minor", 'del_line', 'DEL-L') .. + mtos.theme:get_button('6,5;2,1', "minor", 'del_all', 'DEL-A') return formspec end, @@ -56,7 +56,7 @@ laptop.register_app("calculator", { if fields.number then -- simple number entry - entry.var2 = (entry.var2 or "")..fields.number + entry.var2 = (entry.var2 or "")..minetest.strip_colors(fields.number) elseif fields.del_char then -- delete char if entry.var2 and entry.var2 ~= "" then @@ -92,6 +92,7 @@ laptop.register_app("calculator", { elseif fields.del_all then data.tab = nil elseif fields.operator then + fields.operator = minetest.strip_colors(fields.operator) local entry = data.tab[#data.tab] -- no previous operator if not entry.operator then @@ -118,6 +119,9 @@ laptop.register_app("calculator", { elseif entry.operator == '=' then result = tonumber(entry.var2) end + if not result then + result = 0 + end if fields.operator == '=' then table.insert(data.tab, {var2 = tostring(result)}) else diff --git a/apps/launcher_app.lua b/apps/launcher_app.lua index 9ea68d9..d1b261f 100644 --- a/apps/launcher_app.lua +++ b/apps/launcher_app.lua @@ -33,7 +33,7 @@ laptop.register_app("launcher", { formspec = formspec..'background[0,0;15,10;'..mtos.theme.app_bg..';true]' end if #mtos.appdata.os.stack > 0 then - formspec = formspec..'image_button[-0.29,-0.31;1.09,0.61;'..mtos.theme.back_button..';os_back;<]' --TODO: if stack exists + formspec = formspec..'image_button[-0.29,-0.31;1.09,0.61;'..mtos.theme.back_button..';os_back;<]' end if app.app_info then if #mtos.appdata.os.stack > 0 then diff --git a/apps/launcher_settings_app.lua b/apps/launcher_settings_app.lua index 8170783..1a8d03d 100644 --- a/apps/launcher_settings_app.lua +++ b/apps/launcher_settings_app.lua @@ -20,7 +20,7 @@ laptop.register_app("launcher_settings", { local current_theme = mtos:get_theme(current_theme_name) local current_idx - local formspec = "label[0,0.5;Select theme]" + local formspec = mtos.theme:get_label('0,0.5', "Select theme") local formspec = formspec.."textlist[0,1;5,2;sel_theme;" for i, theme in ipairs(themes_tab) do @@ -41,7 +41,7 @@ laptop.register_app("launcher_settings", { formspec = formspec.."image[5.5,1;5,3.75;"..current_theme.launcher_bg.."]" end - formspec = formspec..'image_button[-0.14,3;3,1;'..current_theme.major_button..';theme_apply;Apply]' + formspec = formspec .. mtos.theme:get_button('0,3.2;2.5,0.6', 'major', 'theme_apply', 'Apply', 'Apply theme') return formspec end, @@ -58,7 +58,6 @@ laptop.register_app("launcher_settings", { if fields.theme_apply and settings_data.selected_theme then mtos:set_theme(settings_data.selected_theme) settings_data.selected_theme = nil - app:exit_app() end end }) diff --git a/apps/mail_app.lua b/apps/mail_app.lua index 3c7589b..12d57f4 100644 --- a/apps/mail_app.lua +++ b/apps/mail_app.lua @@ -79,35 +79,35 @@ laptop.register_app("mail", { -- toggle inbox/sentbox if account.selected_box == "inbox" then - formspec = formspec .. "image_button[0,9;1.5,1;"..mtos.theme.minor_button..";switch_sentbox;Sentbox]tooltip[switch_sentbox;Show sent messages]" + formspec = formspec .. mtos.theme:get_button('0,9;1.5,1', 'minor', 'switch_sentbox', 'Sentbox', 'Show sent messages') else - formspec = formspec .. "image_button[0,9;1.5,1;"..mtos.theme.minor_button..";switch_inbox;Inbox]tooltip[switch_inbox;Show received messages]" + formspec = formspec .. mtos.theme:get_button('0,9;1.5,1', 'minor', 'switch_inbox', 'Inbox', 'Show received messages') end - formspec = formspec .. "image_button[1.7,9;1,1;laptop_email_new.png;new;]tooltip[new;New message]" + formspec = formspec .. "image_button[1.7,9;1,1;"..mtos.theme.minor_button.."^laptop_email_new.png;new;]tooltip[new;New message]" if account.newmessage then - formspec = formspec .. "image_button[2.7,9;1,1;laptop_email_edit.png;continue;]tooltip[continue;Continue last message]" + formspec = formspec .. "image_button[2.7,9;1,1;"..mtos.theme.minor_button.."^laptop_email_edit.png;continue;]tooltip[continue;Continue last message]" end if account.selectedmessage then formspec = formspec .. - "image_button[3.7,9;1,1;laptop_email_reply.png;reply;]tooltip[reply;Reply]".. - "image_button[4.7,9;1,1;laptop_email_forward.png;forward;]tooltip[forward;Forward]".. - "image_button[5.7,9;1,1;laptop_email_trash.png;delete;]tooltip[delete;Delete]" + "image_button[3.7,9;1,1;"..mtos.theme.minor_button.."^laptop_email_reply.png;reply;]tooltip[reply;Reply]".. + "image_button[4.7,9;1,1;"..mtos.theme.minor_button.."^laptop_email_forward.png;forward;]tooltip[forward;Forward]".. + "image_button[5.7,9;1,1;"..mtos.theme.minor_button.."^laptop_email_trash.png;delete;]tooltip[delete;Delete]" if account.selected_box == "inbox" then if not account.selectedmessage.is_read then - formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail_read.png;markread;]tooltip[markread;Mark message as read]" + formspec = formspec .. "image_button[6.7,9;1,1;"..mtos.theme.minor_button.."^laptop_mail_read.png;markread;]tooltip[markread;Mark message as read]" else - formspec = formspec .. "image_button[6.7,9;1,1;laptop_mail.png;markunread;]tooltip[markunread;Mark message as unread]" + formspec = formspec .. "image_button[6.7,9;1,1;"..mtos.theme.minor_button.."^laptop_mail.png;markunread;]tooltip[markunread;Mark message as unread]" end end if account.selected_box == "inbox" then - formspec = formspec .. "label[8,0.5;From: "..(minetest.formspec_escape(account.selectedmessage.sender) or "").."]" + formspec = formspec .. mtos.theme:get_label('8,0.5', "From: "..(account.selectedmessage.sender or "")) else - formspec = formspec .. "label[8,0.5;To: "..(minetest.formspec_escape(account.selectedmessage.receiver) or "").."]" + formspec = formspec .. mtos.theme:get_label('8,0.5', "To: "..(account.selectedmessage.receiver or "")) end - formspec = formspec .. "label[8,1;Subject: "..(minetest.formspec_escape(account.selectedmessage.subject) or "").. + formspec = formspec .. mtos.theme:get_label('8,1', "Subject: "..(account.selectedmessage.subject or "")).. "]textarea[8.25,1.5;7,8.35;body;;"..(minetest.formspec_escape(account.selectedmessage.body) or "").."]" end return formspec @@ -120,6 +120,10 @@ laptop.register_app("mail", { local cloud = app:get_cloud_storage_ref("mail") local account = cloud[mtos.appdata.os.last_player] + if not account then + mtos:set_app() -- wrong player. Back to launcher + return + end account.selected_box = account.selected_box or "inbox" local box = account[account.selected_box] -- inbox or outbox @@ -177,8 +181,8 @@ laptop.register_app("mail", { laptop.register_view("mail:newplayer", { formspec_func = function(app, mtos) - return "label[1,3;No mail account for player "..mtos.appdata.os.last_player.. " found. Do you like to create a new account?]".. - "image_button[1,4;3,1;"..mtos.theme.major_button..';create;Create account]' + return mtos.theme:get_label('1,3', "No mail account for player "..mtos.appdata.os.last_player.. " found. Do you like to create a new account?").. + mtos.theme:get_button('1,4;3,1', 'major', 'create', 'Create account') end, receive_fields_func = function(app, mtos, fields, sender) if sender:get_player_name() ~= mtos.appdata.os.last_player then @@ -209,7 +213,7 @@ laptop.register_view("mail:compose", { local formspec = "field[0.25,1;4,1;receiver;To:;%s]field[0.25,2;4,1;subject;Subject:;%s]textarea[0.25,3;8,4;body;;%s]button[5,8;2,1;send;Send]" formspec = string.format(formspec,minetest.formspec_escape(message.receiver or ""),minetest.formspec_escape(message.subject or ""),minetest.formspec_escape(message.body or "")) if message.receiver and not cloud[message.receiver] then - formspec = formspec.."label[7,8;invalid receiver player]" + formspec = formspec..mtos.theme:get_label('7,8', "invalid receiver player") end return formspec end, diff --git a/demo_apps.lua b/demo_apps.lua index a33f888..c96f03e 100644 --- a/demo_apps.lua +++ b/demo_apps.lua @@ -4,7 +4,7 @@ laptop.register_app("demo1", { app_icon = "laptop_setting_wrench.png", app_info = "The first and simple demo app", formspec_func = function(app, mtos) - return 'image_button[5,5;3,1;'..mtos.theme.major_button..';next;Second screen]' + return mtos.theme:get_button('5,5;3,1', 'major', 'next', 'Second screen') end, receive_fields_func = function(app, mtos, fields, sender) if fields.next then @@ -16,7 +16,7 @@ laptop.register_app("demo1", { laptop.register_view("demo1_view2", { app_info = "Second screen in Demo App 1", formspec_func = function(app, mtos) - return "label[1,5;Use the framework buttons to navigate back or cancel]" + return mtos.theme:get_label('1,5', "Use the framework buttons to navigate back or cancel") end, receive_fields_func = function(app, mtos, fields, sender) end diff --git a/os.lua b/os.lua index d831678..25052fa 100644 --- a/os.lua +++ b/os.lua @@ -58,16 +58,7 @@ end -- Get given or current theme function os_class:get_theme(theme) local theme_sel = theme or self.appdata.os.theme - local ret = table.copy(laptop.themes.default) - if theme_sel and laptop.themes[theme_sel] then - for k,v in pairs(laptop.themes[theme_sel]) do - ret[k] = v - end - ret.name = theme_sel - else - ret.name = "default" - end - return ret + return laptop.get_theme(theme_sel) end -- Set current theme diff --git a/themes.lua b/themes.lua index c4ef4f2..10c4884 100644 --- a/themes.lua +++ b/themes.lua @@ -7,6 +7,7 @@ laptop.themes = { back_button = "laptop_theme_freedom_back_button.png", exit_button = "laptop_theme_freedom_exit_button.png", app_button = "laptop_theme_freedom_app_button.png", + textcolor = "#000000", }, } @@ -25,4 +26,30 @@ for _, file in ipairs(theme_list) do if file:sub(-10) == '_theme.lua' then dofile(theme_path..file) end -end \ No newline at end of file +end + +local theme_class = {} +theme_class.__index = theme_class + +-- get prepared button textures +function theme_class:get_button(area, prefix, code, text, tooltip) + return'image_button['..area..';'..self[prefix.."_button"]..';'..code..';'.. minetest.colorize(self[prefix.."_textcolor"] or self.textcolor,minetest.formspec_escape(text))..']'.. + "tooltip["..code..";"..minetest.formspec_escape(tooltip or text).."]" +end +-- Get themed label +function theme_class:get_label(area, label) + return'label['..area..';'..minetest.colorize(self.textcolor, minetest.formspec_escape(label))..']' +end + +function laptop.get_theme(theme_name) + local self = setmetatable(table.copy(laptop.themes.default), theme_class) + if theme_name and laptop.themes[theme_name] then + for k,v in pairs(laptop.themes[theme_name]) do + self[k] = v + end + self.name = theme_name + else + self.name = "default" + end + return self +end From 9f1865ccaf35901c30f1538fd59096a0991a7931 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Mon, 11 Dec 2017 11:05:54 +0100 Subject: [PATCH 11/14] launcher: clock major button themed --- apps/launcher_app.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/launcher_app.lua b/apps/launcher_app.lua index d1b261f..230fad7 100644 --- a/apps/launcher_app.lua +++ b/apps/launcher_app.lua @@ -24,7 +24,7 @@ laptop.register_app("launcher", { 'label['..(x-0.3)..','..(y+1)..';'..e.def.app_name..']'.. 'tooltip['..e.name..';'..(e.def.app_info or e.name)..']' --;;]' end - out = out.."image_button[11,9.8;4,0.7;menu_bg.png;os_clock;"..tostring(os.date("%c")).."]" + out = out..mtos.theme:get_button("11,9.8;4,0.7", "major", "os_clock", os.date("%c")) return out end, appwindow_formspec_func = function(launcher_app, app, mtos) From 52f54ba54513a77d5132bbdbb616469b82a6c6c6 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Mon, 11 Dec 2017 11:33:09 +0100 Subject: [PATCH 12/14] workarounded textarea with hardcoded background because of not text color setting possible --- apps/mail_app.lua | 11 ++++++++--- apps/stickynote_app.lua | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/mail_app.lua b/apps/mail_app.lua index 12d57f4..63e5d57 100644 --- a/apps/mail_app.lua +++ b/apps/mail_app.lua @@ -108,7 +108,8 @@ laptop.register_app("mail", { end formspec = formspec .. mtos.theme:get_label('8,1', "Subject: "..(account.selectedmessage.subject or "")).. - "]textarea[8.25,1.5;7,8.35;body;;"..(minetest.formspec_escape(account.selectedmessage.body) or "").."]" + "background[8,1.55;6.92,7.3;gui_formbg.png]".. + "textarea[8.25,1.5;7,8.35;body;;"..(minetest.formspec_escape(account.selectedmessage.body) or "").."]" end return formspec end, @@ -210,10 +211,14 @@ laptop.register_view("mail:compose", { account.newmessage = account.newmessage or {} local message = account.newmessage - local formspec = "field[0.25,1;4,1;receiver;To:;%s]field[0.25,2;4,1;subject;Subject:;%s]textarea[0.25,3;8,4;body;;%s]button[5,8;2,1;send;Send]" + local formspec = "background[-0.1,0.4;4.2,2.4;gui_formbg.png]".. + "field[0.25,1;4,1;receiver;To:;%s]field[0.25,2;4,1;subject;Subject:;%s]".. + "background[0,3.05;7.95,3.44;gui_formbg.png]".. + "textarea[0.25,3;8,4;body;;%s]".. + mtos.theme:get_button("0,8;2,1", "major", "send", "Send message") formspec = string.format(formspec,minetest.formspec_escape(message.receiver or ""),minetest.formspec_escape(message.subject or ""),minetest.formspec_escape(message.body or "")) if message.receiver and not cloud[message.receiver] then - formspec = formspec..mtos.theme:get_label('7,8', "invalid receiver player") + formspec = formspec..mtos.theme:get_label('2.3,8', "invalid receiver player") end return formspec end, diff --git a/apps/stickynote_app.lua b/apps/stickynote_app.lua index b635e7e..85ff5b1 100644 --- a/apps/stickynote_app.lua +++ b/apps/stickynote_app.lua @@ -6,7 +6,8 @@ laptop.register_app("stickynote", { local data = app:get_storage_ref() data.text = data.text or "" - return "textarea[0.35,0.35;15.08,10.5;text;;"..minetest.formspec_escape(data.text).."]" + return "background[0,0.35;15.2,9.2;gui_formbg.png]".. + "textarea[0.35,0.35;15.08,10.5;text;;"..minetest.formspec_escape(data.text).."]" end, receive_fields_func = function(app, os, fields, sender) if fields.text then From 7f69ada7b5455bd0214939117fbeff9a02978549 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Mon, 11 Dec 2017 11:47:21 +0100 Subject: [PATCH 13/14] converted themes to unix lineendings added textcolor to API.md set basic theme textcolor to white --- API.md | 1 + themes/basic_theme.lua | 19 ++++++++++--------- themes/blue_theme.lua | 16 ++++++++-------- themes/cubic_theme.lua | 16 ++++++++-------- themes/magma_theme.lua | 16 ++++++++-------- themes/red_theme.lua | 16 ++++++++-------- 6 files changed, 43 insertions(+), 41 deletions(-) diff --git a/API.md b/API.md index 473305b..56bdc4d 100644 --- a/API.md +++ b/API.md @@ -72,6 +72,7 @@ Definitiontable: - `exit_button` Exit button image - `major_button` Major (highlighted) button image - `minor_button` Minor button image +- `textcolor` Default text color for buttons and labels. For buttons the major_textcolor and minor_textcolor supported ## Theme methods `function laptop.get_theme(theme_name)` diff --git a/themes/basic_theme.lua b/themes/basic_theme.lua index 1b53097..6cef136 100644 --- a/themes/basic_theme.lua +++ b/themes/basic_theme.lua @@ -1,9 +1,10 @@ -laptop.register_theme("Basic", { - launcher_bg = "laptop_theme_basic_launcher_bg.png", - app_bg = "laptop_theme_basic_app_bg.png", - major_button = "laptop_theme_basic_button.png", - minor_button = "laptop_theme_basic_button.png", - back_button = "blank.png", - exit_button = "blank.png", - app_button = "blank.png", -}) \ No newline at end of file +laptop.register_theme("Basic", { + launcher_bg = "laptop_theme_basic_launcher_bg.png", + app_bg = "laptop_theme_basic_app_bg.png", + major_button = "laptop_theme_basic_button.png", + minor_button = "laptop_theme_basic_button.png", + back_button = "blank.png", + exit_button = "blank.png", + app_button = "blank.png", + textcolor = "#FFFFFF", +}) diff --git a/themes/blue_theme.lua b/themes/blue_theme.lua index 21d8f2f..87fc4a4 100644 --- a/themes/blue_theme.lua +++ b/themes/blue_theme.lua @@ -1,9 +1,9 @@ -laptop.register_theme("Blue", { - launcher_bg = "laptop_theme_blue_launcher_bg.png", - app_bg = "laptop_theme_blue_app_bg.png", - major_button = "laptop_theme_blue_major_button.png", - minor_button = "laptop_theme_minor_button.png", - back_button = "laptop_theme_blue_back_button.png", - exit_button = "laptop_theme_blue_exit_button.png", - app_button = "laptop_theme_blue_app_button.png", +laptop.register_theme("Blue", { + launcher_bg = "laptop_theme_blue_launcher_bg.png", + app_bg = "laptop_theme_blue_app_bg.png", + major_button = "laptop_theme_blue_major_button.png", + minor_button = "laptop_theme_minor_button.png", + back_button = "laptop_theme_blue_back_button.png", + exit_button = "laptop_theme_blue_exit_button.png", + app_button = "laptop_theme_blue_app_button.png", }) \ No newline at end of file diff --git a/themes/cubic_theme.lua b/themes/cubic_theme.lua index 57637e1..18b5a3d 100644 --- a/themes/cubic_theme.lua +++ b/themes/cubic_theme.lua @@ -1,9 +1,9 @@ -laptop.register_theme("Cubic", { - launcher_bg = "laptop_theme_cubic_launcher_bg.png", - app_bg = "laptop_theme_cubic_app_bg.png", - major_button = "laptop_theme_cubic_major_button.png", - minor_button = "laptop_theme_minor_button.png", - back_button = "laptop_theme_cubic_back_button.png", - exit_button = "laptop_theme_cubic_exit_button.png", - app_button = "laptop_theme_cubic_app_button.png", +laptop.register_theme("Cubic", { + launcher_bg = "laptop_theme_cubic_launcher_bg.png", + app_bg = "laptop_theme_cubic_app_bg.png", + major_button = "laptop_theme_cubic_major_button.png", + minor_button = "laptop_theme_minor_button.png", + back_button = "laptop_theme_cubic_back_button.png", + exit_button = "laptop_theme_cubic_exit_button.png", + app_button = "laptop_theme_cubic_app_button.png", }) \ No newline at end of file diff --git a/themes/magma_theme.lua b/themes/magma_theme.lua index 497626f..b5570c6 100644 --- a/themes/magma_theme.lua +++ b/themes/magma_theme.lua @@ -1,9 +1,9 @@ -laptop.register_theme("Magma", { - launcher_bg = "laptop_theme_magma_launcher_bg.png", - app_bg = "laptop_theme_magma_app_bg.png", - major_button = "laptop_theme_magma_major_button.png", - minor_button = "laptop_theme_minor_button.png", - back_button = "laptop_theme_magma_back_button.png", - exit_button = "laptop_theme_magma_exit_button.png", - app_button = "laptop_theme_magma_app_button.png", +laptop.register_theme("Magma", { + launcher_bg = "laptop_theme_magma_launcher_bg.png", + app_bg = "laptop_theme_magma_app_bg.png", + major_button = "laptop_theme_magma_major_button.png", + minor_button = "laptop_theme_minor_button.png", + back_button = "laptop_theme_magma_back_button.png", + exit_button = "laptop_theme_magma_exit_button.png", + app_button = "laptop_theme_magma_app_button.png", }) \ No newline at end of file diff --git a/themes/red_theme.lua b/themes/red_theme.lua index 0a6c4c6..b435dcd 100644 --- a/themes/red_theme.lua +++ b/themes/red_theme.lua @@ -1,9 +1,9 @@ -laptop.register_theme("Red", { - launcher_bg = "laptop_theme_red_launcher_bg.png", - app_bg = "laptop_theme_red_app_bg.png", - major_button = "laptop_theme_red_major_button.png", - minor_button = "laptop_theme_minor_button.png", - back_button = "laptop_theme_red_back_button.png", - exit_button = "laptop_theme_red_exit_button.png", - app_button = "laptop_theme_red_app_button.png", +laptop.register_theme("Red", { + launcher_bg = "laptop_theme_red_launcher_bg.png", + app_bg = "laptop_theme_red_app_bg.png", + major_button = "laptop_theme_red_major_button.png", + minor_button = "laptop_theme_minor_button.png", + back_button = "laptop_theme_red_back_button.png", + exit_button = "laptop_theme_red_exit_button.png", + app_button = "laptop_theme_red_app_button.png", }) \ No newline at end of file From 3a41e882cbfc9c8ad678272298bba387b412b34f Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Mon, 11 Dec 2017 15:19:22 +0100 Subject: [PATCH 14/14] calculator: be more centric --- apps/calculator_app.lua | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/apps/calculator_app.lua b/apps/calculator_app.lua index 5b2e5f5..4bb9585 100644 --- a/apps/calculator_app.lua +++ b/apps/calculator_app.lua @@ -13,10 +13,10 @@ laptop.register_app("calculator", { end local formspec = "tablecolumns[" .. - "text,align=right,padding=1.5,width=6;".. -- first value + "text,align=right,padding=1.5,width=10;".. -- first value "text,align=right,padding=1.5;".. -- operator - "text,align=right,padding=1.5,width=6]".. -- last value - "table[0.9,0.8;7,2;tab;" + "text,align=right,padding=1.5,width=10]".. -- last value + "table[3.9,0.8;7,2;tab;" for idx,entry in ipairs(data.tab) do if idx > 1 then @@ -26,27 +26,27 @@ laptop.register_app("calculator", { end formspec = formspec .. ";"..#data.tab.."]".. - mtos.theme:get_button('1,3;1,1', "minor", 'number', '1') .. - mtos.theme:get_button('2,3;1,1', "minor", 'number', '2') .. - mtos.theme:get_button('3,3;1,1', "minor", 'number', '3') .. - mtos.theme:get_button('1,4;1,1', "minor", 'number', '4') .. - mtos.theme:get_button('2,4;1,1', "minor", 'number', '5') .. - mtos.theme:get_button('3,4;1,1', "minor", 'number', '6') .. - mtos.theme:get_button('1,5;1,1', "minor", 'number', '7') .. - mtos.theme:get_button('2,5;1,1', "minor", 'number', '8') .. - mtos.theme:get_button('3,5;1,1', "minor", 'number', '9') .. - mtos.theme:get_button('1,6;1,1', "minor", 'number', '0') .. - mtos.theme:get_button('2,6;1,1', "minor", 'number', '.') .. + mtos.theme:get_button('4,3;1,1', "minor", 'number', '1') .. + mtos.theme:get_button('5,3;1,1', "minor", 'number', '2') .. + mtos.theme:get_button('6,3;1,1', "minor", 'number', '3') .. + mtos.theme:get_button('4,4;1,1', "minor", 'number', '4') .. + mtos.theme:get_button('5,4;1,1', "minor", 'number', '5') .. + mtos.theme:get_button('6,4;1,1', "minor", 'number', '6') .. + mtos.theme:get_button('4,5;1,1', "minor", 'number', '7') .. + mtos.theme:get_button('5,5;1,1', "minor", 'number', '8') .. + mtos.theme:get_button('6,5;1,1', "minor", 'number', '9') .. + mtos.theme:get_button('4,6;1,1', "minor", 'number', '0') .. + mtos.theme:get_button('5,6;1,1', "minor", 'number', '.') .. - mtos.theme:get_button('5,3;1,1', "minor", 'operator', '+') .. - mtos.theme:get_button('5,4;1,1', "minor", 'operator', '-') .. - mtos.theme:get_button('5,5;1,1', "minor", 'operator', '/') .. - mtos.theme:get_button('5,6;1,1', "minor", 'operator', '*') .. - mtos.theme:get_button('6,6;2,1', "minor", 'operator', '=') .. + mtos.theme:get_button('8,3;1,1', "minor", 'operator', '+') .. + mtos.theme:get_button('8,4;1,1', "minor", 'operator', '-') .. + mtos.theme:get_button('8,5;1,1', "minor", 'operator', '/') .. + mtos.theme:get_button('8,6;1,1', "minor", 'operator', '*') .. + mtos.theme:get_button('9,6;2,1', "minor", 'operator', '=') .. - mtos.theme:get_button('6,3;2,1', "minor", 'del_char', 'DEL-1') .. - mtos.theme:get_button('6,4;2,1', "minor", 'del_line', 'DEL-L') .. - mtos.theme:get_button('6,5;2,1', "minor", 'del_all', 'DEL-A') + mtos.theme:get_button('9,3;2,1', "minor", 'del_char', 'DEL-1') .. + mtos.theme:get_button('9,4;2,1', "minor", 'del_line', 'DEL-L') .. + mtos.theme:get_button('9,5;2,1', "minor", 'del_all', 'DEL-A') return formspec end,