762 lines
22 KiB
Lua
762 lines
22 KiB
Lua
--[[
|
|
|
|
Touch screen designer.
|
|
|
|
Simple WYSIWYG editor for touch screens.
|
|
Can export configuration through digiline
|
|
or through touch screen multi line text field.
|
|
|
|
Author: SX
|
|
|
|
--]]
|
|
|
|
local GRID_SIZE = mem.GRID_SIZE and mem.GRID_SIZE or 0.4
|
|
|
|
local initialize_designer = function()
|
|
|
|
mem.ALLOW_RESIZE_W = {
|
|
addfield = 1,
|
|
addpwdfield = 1,
|
|
addbutton = 1,
|
|
addimage_button = 1,
|
|
addtextarea = 1,
|
|
addtextlist = 1,
|
|
adddropdown = 1,
|
|
addimage = 1,
|
|
}
|
|
mem.ALLOW_RESIZE_H = {
|
|
addimage_button = 1,
|
|
addtextarea = 1,
|
|
addtextlist = 1,
|
|
addimage = 1,
|
|
}
|
|
mem.SELECTABLE_COMPONENTS = {
|
|
button = 1,
|
|
buttonexit = 1,
|
|
imagebutton = 1,
|
|
imagebuttonexit = 1,
|
|
}
|
|
mem.WORKSPACE_CONTROL = {
|
|
command = 'addimage_button',
|
|
image = 'signs_road_red.png',
|
|
name = '_ctrl',
|
|
type = 'ctrl',
|
|
label = '.',
|
|
W = 0.4,
|
|
H = 0.4,
|
|
}
|
|
mem.CTRL_OFFSET = {
|
|
addfield = {
|
|
X = -0.3,
|
|
Y = -0.4,
|
|
},
|
|
addpwdfield = {
|
|
X = -0.3,
|
|
Y = -0.4,
|
|
},
|
|
}
|
|
mem.COMPONENT_DEFAULTS = {
|
|
button = {
|
|
command = 'addbutton',
|
|
name = '_button_',
|
|
label = 'untitled',
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 1.6,
|
|
H = 0.8,
|
|
},
|
|
buttonexit = {
|
|
variant = '_exit',
|
|
command = 'addbutton',
|
|
name = '_buttonexit_',
|
|
label = 'untitled',
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 1.6,
|
|
H = 0.8,
|
|
},
|
|
imagebutton = {
|
|
command = 'addimage_button',
|
|
name = "_imagebutton_",
|
|
label = "untitled",
|
|
image = 'wool_yellow.png',
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 1.6,
|
|
H = 0.8,
|
|
},
|
|
imagebuttonexit = {
|
|
variant = '_exit',
|
|
command = 'addimage_button',
|
|
name = "_imagebuttonexit_",
|
|
label = "untitled",
|
|
image = 'wool_yellow.png',
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 1.6,
|
|
H = 0.8,
|
|
},
|
|
field = {
|
|
command = 'addfield',
|
|
name = '_field_',
|
|
label = 'untitled',
|
|
default = 'value',
|
|
X = 0.7,
|
|
Y = 0.7,
|
|
W = 1.6,
|
|
H = 0.8,
|
|
},
|
|
pwdfield = {
|
|
command = 'addpwdfield',
|
|
name = '_pwdfield_',
|
|
label = 'untitled',
|
|
X = 0.7,
|
|
Y = 0.7,
|
|
W = 1.6,
|
|
H = 0.8,
|
|
},
|
|
label = {
|
|
command = 'addlabel',
|
|
label = 'untitled',
|
|
name = '_label_', -- Deleted on export, required for editor
|
|
X = 0.7,
|
|
Y = 0.7,
|
|
W = 1.2, -- Deleted on export, required for editor
|
|
H = 0.8, -- Deleted on export, required for editor
|
|
},
|
|
vertlabel = {
|
|
command = 'addvertlabel',
|
|
label = 'untitled',
|
|
name = '_vertlabel_', -- Deleted on export, required for editor
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 0.8, -- Deleted on export, required for editor
|
|
H = 1.2, -- Deleted on export, required for editor
|
|
},
|
|
textarea = {
|
|
command = "addtextarea",
|
|
label = "untitled",
|
|
name = "_textarea_",
|
|
default = 'value',
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 2.6,
|
|
H = 1.8,
|
|
},
|
|
textlist = {
|
|
command = "addtextlist",
|
|
label = "untitled",
|
|
name = "_textlist_",
|
|
listelements = {},
|
|
transparent = false,
|
|
selected_id = 1,
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 2.6,
|
|
H = 1.8,
|
|
},
|
|
dropdown = {
|
|
command = "adddropdown",
|
|
label = "untitled",
|
|
name = "_dropdown_",
|
|
choices = {},
|
|
selected_id = 1,
|
|
X = 0.8,
|
|
Y = 0.8,
|
|
W = 1.6,
|
|
H = 0.8,
|
|
},
|
|
}
|
|
mem.COMPONENT_TYPES = {}
|
|
for k,_ in pairs(mem.COMPONENT_DEFAULTS) do
|
|
table.insert(mem.COMPONENT_TYPES, k)
|
|
end
|
|
end
|
|
|
|
local ALLOW_RESIZE_W = mem.ALLOW_RESIZE_W
|
|
local ALLOW_RESIZE_H = mem.ALLOW_RESIZE_H
|
|
local SELECTABLE_COMPONENTS = mem.SELECTABLE_COMPONENTS
|
|
local WORKSPACE_CONTROL = mem.WORKSPACE_CONTROL
|
|
local CTRL_OFFSET = mem.CTRL_OFFSET
|
|
local COMPONENT_DEFAULTS = mem.COMPONENT_DEFAULTS
|
|
local COMPONENT_TYPES = mem.COMPONENT_TYPES
|
|
|
|
local draw_designer = function()
|
|
local ui = {
|
|
{
|
|
command = "addbutton_exit", X=9.6, Y=-0.31, W=0.7, H=0.7,
|
|
name = "quit", label = "X"
|
|
},
|
|
}
|
|
|
|
if mem.draw_code then
|
|
digiline_send("touch", mem.touch_clear_commands)
|
|
table.insert(ui, {
|
|
command = "addbutton", X=9.5, Y=0.49, W=0.8, H=0.8,
|
|
name = "close_code", label = "[[>"
|
|
})
|
|
table.insert(ui, {
|
|
command = "addtextarea", X=0.5, Y=0.5, W=9, H=8.5,
|
|
name = "result", label = "Generated Touch Screen configuration code", default = mem.code
|
|
})
|
|
else
|
|
table.insert(ui, {
|
|
command = "addbutton", X=mem.draw_toolbar and 9.45 or 9.65, Y=0.5, W=mem.draw_toolbar and 0.85 or 0.65, H=0.8,
|
|
name = "hide_toolbar", label = mem.draw_toolbar and "[[>" or "<]]"
|
|
})
|
|
if not mem.draw_component_editor and mem.draw_workspace then
|
|
digiline_send("touch", mem.workspace)
|
|
else
|
|
digiline_send("touch", { command = "clear" })
|
|
end
|
|
if mem.draw_toolbar then
|
|
-- Static toolbar components
|
|
digiline_send("touch", mem.toolbar)
|
|
-- Dynamic toolbar components
|
|
digiline_send("touch", {
|
|
{
|
|
command = "addbutton", X=8.45, Y=0.5, W=0.7, H=0.8,
|
|
name = "toggle_grid_size", label = string.format('%.1f', GRID_SIZE)
|
|
},{
|
|
command = "addbutton", X=8.95, Y=1.2, W=0.7, H=0.8,
|
|
name = 'toggle_size_move', label = (mem.mode_move and 'move' or 'size')
|
|
},{
|
|
command = "addbutton", X=8.45, Y=1.9, W=0.7, H=0.8,
|
|
name = "edit_component", label = "edit"
|
|
},{
|
|
command = "addlabel", X=8.6, Y=3.3,
|
|
label = mem.selected.ref and string.format('X:%.1f Y:%.1f\nW:%.1f H:%.1f', mem.selected.ref.X, mem.selected.ref.Y, mem.selected.ref.W, mem.selected.ref.H) or 'No selection'
|
|
},{
|
|
command = "addfield", X=8.75, Y=4.75, W=1.7, H=0.6,
|
|
name = 'component_name', label = 'Ref. key:',
|
|
default = mem.selected.display_name and mem.selected.display_name or ''
|
|
}
|
|
})
|
|
--[[
|
|
for _,v in pairs(mem.toolbar) do
|
|
table.insert(ui, v)
|
|
end
|
|
table.insert(ui, {
|
|
command = "addfield", X=8.6, Y=4.9, W=1.7, H=0.6,
|
|
name = 'component_name', label = 'Ref. key:',
|
|
default = mem.selected.display_name and mem.selected.display_name or ''
|
|
})
|
|
--]]
|
|
end
|
|
if mem.draw_component_editor then
|
|
local editor_ui= {
|
|
{
|
|
command = 'addimage_button',
|
|
image = 'wool_red.png', X=2.5, Y=4.5, W=2, H=0.8,
|
|
name = "edit_component", label = "Cancel"
|
|
},{
|
|
command = 'addimage_button',
|
|
image = 'wool_green.png', X=4.6, Y=4.5, W=2, H=0.8,
|
|
name = 'component_editor_save', label = 'Save'
|
|
},
|
|
}
|
|
local input_y = 3.8
|
|
if mem.selected.ref.label then
|
|
table.insert(editor_ui, {
|
|
command = "addfield", X=2.8, Y=input_y, W=4, H=0.8,
|
|
name = 'component_label', label = 'Component label:',
|
|
default = mem.selected.ref.label
|
|
})
|
|
input_y = input_y - 1
|
|
end
|
|
if mem.selected.ref.default then
|
|
table.insert(editor_ui, {
|
|
command = "addfield", X=2.8, Y=input_y, W=4, H=0.8,
|
|
name = 'component_default', label = 'Default value:',
|
|
default = mem.selected.ref.default
|
|
})
|
|
input_y = input_y - 1
|
|
end
|
|
if mem.selected.ref.image then
|
|
table.insert(editor_ui, {
|
|
command = "addfield", X=2.8, Y=input_y, W=4, H=0.8,
|
|
name = 'component_image', label = 'Image:',
|
|
default = mem.selected.ref.image
|
|
})
|
|
input_y = input_y - 1
|
|
end
|
|
if mem.selected.ref.choices or mem.selected.ref.listelements then
|
|
table.insert(editor_ui, {
|
|
command = "addfield", X=2.8, Y=input_y, W=2.6, H=0.8,
|
|
name = 'component_listelement', label = 'New entry:',
|
|
default = ''
|
|
})
|
|
table.insert(editor_ui, {
|
|
command = "addbutton", X=5.2, Y=input_y - 0.3, W=0.8, H=0.8,
|
|
name = "component_listelement_add", label = 'Add'
|
|
})
|
|
table.insert(editor_ui, {
|
|
command = "addbutton", X=6, Y=input_y - 0.3, W=0.8, H=0.8,
|
|
name = "component_listelement_del", label = 'Del'
|
|
})
|
|
input_y = input_y - 2.6
|
|
table.insert(editor_ui, {
|
|
command = "addtextlist", X = 2.5, Y = input_y, W = 4, H = 2,
|
|
label = "Item editor:",
|
|
name = "component_editor_items",
|
|
listelements = mem.selected.ref.choices or mem.selected.ref.listelements,
|
|
selected_id = mem.component_editor_items_idx or 1,
|
|
})
|
|
input_y = input_y - 1
|
|
end
|
|
digiline_send("touch", editor_ui)
|
|
end
|
|
end
|
|
digiline_send("touch", ui)
|
|
end
|
|
|
|
local reset = function()
|
|
mem.component_index = {}
|
|
for k,_ in pairs(COMPONENT_DEFAULTS) do
|
|
mem.component_index[k] = 0
|
|
end
|
|
mem.workspace = {
|
|
{ command = "clear" } -- 'clear' command is special case and not indexed in workspace
|
|
}
|
|
mem.workspace_search = {}
|
|
mem.workspace_control = {}
|
|
mem.draw_workspace = true
|
|
mem.draw_toolbar = true
|
|
mem.draw_code = false
|
|
mem.mode_move = true
|
|
mem.locked = false
|
|
mem.code = ''
|
|
mem.selected = {
|
|
display_name = nil,
|
|
ref = nil,
|
|
ctrl = nil
|
|
}
|
|
-- Add only static controls here, keeping cached in memory reduces table constructors
|
|
mem.toolbar = {
|
|
{
|
|
command = "addbutton", X=8.95, Y=0.5, W=0.7, H=0.8,
|
|
name = "up", label = "^"
|
|
},{
|
|
command = "addbutton", X=8.45, Y=1.2, W=0.7, H=0.8,
|
|
name = "left", label = "<"
|
|
},{
|
|
command = "addbutton", X=9.45, Y=1.2, W=0.7, H=0.8,
|
|
name = "right", label = ">"
|
|
},{
|
|
command = "addbutton", X=8.95, Y=1.9, W=0.7, H=0.8,
|
|
name = "down", label = "v"
|
|
},{
|
|
command = "addbutton", X=9.45, Y=1.9, W=0.7, H=0.8,
|
|
name = "delete", label = "del"
|
|
},{
|
|
command = "addbutton", X=8.45, Y=2.6, W=1.7, H=0.8,
|
|
name = "reset", label = "Reset"
|
|
},{
|
|
command = "addtextlist", X=8.45, Y=5.1, W=1.48, H=1.8,
|
|
name="component_type", selected_id=1, listelements = COMPONENT_TYPES
|
|
},{
|
|
command = "addbutton", X=8.45, Y=6.9, W=1.7, H=0.8,
|
|
name = "create", label = "Create"
|
|
},{
|
|
command = "addbutton", X=8.45, Y=7.6, W=1.7, H=0.8,
|
|
name = "code", label = "Generate"
|
|
},
|
|
}
|
|
mem.component_type_id = 1
|
|
end
|
|
|
|
local info = function(msg)
|
|
digiline_send('lcd', msg)
|
|
end
|
|
|
|
local validate_component_name = function(name)
|
|
return type(name) == 'string' and #name > 0
|
|
end
|
|
|
|
local indexof = function(items, value)
|
|
for k,v in pairs(items) do
|
|
if v == value then
|
|
return k
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local textlist_indexof = function(value)
|
|
if #value >= 5 and string.sub(value, 1, 4) == 'CHG:' then
|
|
return tonumber(string.sub(value, 5, #value))
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local update_control_position = function(control, component)
|
|
if control then
|
|
if CTRL_OFFSET[component.command] then
|
|
control.X = component.X + CTRL_OFFSET[component.command].X
|
|
control.Y = component.Y + CTRL_OFFSET[component.command].Y
|
|
else
|
|
control.X = component.X
|
|
control.Y = component.Y
|
|
end
|
|
end
|
|
end
|
|
|
|
local get_next_unused_name = function(component_type, name)
|
|
local i = 1
|
|
local result = name
|
|
local prefix = COMPONENT_DEFAULTS[component_type].name
|
|
while mem.workspace_search[prefix .. result] do
|
|
-- add numbers until free unused name is found
|
|
result = name .. '_' .. i
|
|
end
|
|
return result
|
|
end
|
|
|
|
local create_component_name = function(component_type, name)
|
|
if not COMPONENT_DEFAULTS[component_type] then
|
|
return false
|
|
end
|
|
if validate_component_name(name) then
|
|
-- attempt to use supplied component name
|
|
return get_next_unused_name(component_type, name)
|
|
else
|
|
-- generate new component name
|
|
mem.component_index[component_type] = mem.component_index[component_type] + 1
|
|
return get_next_unused_name(component_type, component_type .. mem.component_index[component_type])
|
|
end
|
|
end
|
|
|
|
local create_component = function(component_type, name)
|
|
local result = {}
|
|
for k,v in pairs(COMPONENT_DEFAULTS[component_type]) do
|
|
if type(v) == 'table' then
|
|
result[k] = {'value'} -- Avoid references to default component values
|
|
else
|
|
result[k] = v
|
|
end
|
|
end
|
|
result.type = component_type
|
|
if result.name then
|
|
result.name = result.name .. name
|
|
end
|
|
return result
|
|
end
|
|
|
|
local create_control_component = function(component)
|
|
local result = {}
|
|
for k,v in pairs(WORKSPACE_CONTROL) do
|
|
result[k] = v
|
|
end
|
|
result.name = result.name .. component.name
|
|
update_control_position(result, component)
|
|
return result
|
|
end
|
|
|
|
local move_component = function(selection, X, Y)
|
|
if selection.ref then
|
|
if X ~= nil and selection.ref.X + X >= 0 and selection.ref.X + selection.ref.W + X <= 10 then
|
|
selection.ref.X = selection.ref.X + X
|
|
end
|
|
if Y ~= nil and selection.ref.Y + Y >= 0 and selection.ref.Y + selection.ref.H + Y <= 8 then
|
|
selection.ref.Y = selection.ref.Y + Y
|
|
end
|
|
update_control_position(selection.ctrl, selection.ref)
|
|
end
|
|
end
|
|
|
|
local resize_component = function(selection, W, H)
|
|
if not selection.ref then
|
|
return false
|
|
end
|
|
local enable_W = ALLOW_RESIZE_W[selection.ref.command] and true or false
|
|
local enable_H = ALLOW_RESIZE_H[selection.ref.command] and true or false
|
|
if selection.ref.W and selection.ref.H then
|
|
if enable_W and W ~= nil and selection.ref.W >= GRID_SIZE and selection.ref.W <= 10 then
|
|
selection.ref.W = selection.ref.W + W
|
|
end
|
|
if enable_H and H ~= nil and selection.ref.H >= GRID_SIZE and selection.ref.H <= 10 then
|
|
selection.ref.H = selection.ref.H + H
|
|
end
|
|
else
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
local nice_name = function(name)
|
|
local name_idx = string.find(name, "_", 2, true)
|
|
return string.sub(name, name_idx + 1, #name)
|
|
end
|
|
|
|
local deselect = function()
|
|
mem.selected.ref = nil
|
|
mem.selected.ctrl = nil
|
|
mem.selected.display_name = nil
|
|
mem.draw_component_editor = false
|
|
mem.component_editor_items_idx = nil
|
|
end
|
|
|
|
local select_component = function(name)
|
|
if mem.workspace_search[name] then
|
|
mem.selected.ref = mem.workspace[mem.workspace_search[name]]
|
|
mem.selected.ctrl = nil
|
|
mem.selected.display_name = nice_name(name)
|
|
return true
|
|
elseif mem.workspace_control[name] then
|
|
local main_name_idx = string.find(name, "_", #WORKSPACE_CONTROL.name + 1, true)
|
|
local main_name = string.sub(name, main_name_idx, #name)
|
|
mem.selected.ctrl = mem.workspace[mem.workspace_control[name]]
|
|
mem.selected.ref = mem.workspace[mem.workspace_search[main_name]]
|
|
mem.selected.display_name = nice_name(main_name)
|
|
return true
|
|
end
|
|
deselect()
|
|
return false
|
|
end
|
|
|
|
local workspace_cleanup = function()
|
|
mem.workspace_search = {}
|
|
mem.workspace_control = {}
|
|
workspace = {{command='clear'}}
|
|
for index,component in pairs(mem.workspace) do
|
|
if component and component.name and component.type ~= 'ctrl' then
|
|
table.insert(workspace, component)
|
|
mem.workspace_search[component.name] = table.maxn(workspace)
|
|
if not SELECTABLE_COMPONENTS[component.type] then
|
|
-- Add control anchor button to allow passive component selection
|
|
local control = create_control_component(component)
|
|
table.insert(workspace, control)
|
|
mem.workspace_control[control.name] = table.maxn(workspace)
|
|
end
|
|
end
|
|
end
|
|
mem.workspace = workspace
|
|
end
|
|
|
|
local functions = {
|
|
up = function()
|
|
if mem.mode_move then
|
|
move_component(mem.selected, nil, -GRID_SIZE)
|
|
else
|
|
resize_component(mem.selected, nil, GRID_SIZE)
|
|
end
|
|
end,
|
|
down = function()
|
|
if mem.mode_move then
|
|
move_component(mem.selected, nil, GRID_SIZE)
|
|
else
|
|
resize_component(mem.selected, nil, -GRID_SIZE)
|
|
end
|
|
end,
|
|
left = function()
|
|
if mem.mode_move then
|
|
move_component(mem.selected, -GRID_SIZE, nil)
|
|
else
|
|
resize_component(mem.selected, -GRID_SIZE, nil)
|
|
end
|
|
end,
|
|
right = function()
|
|
if mem.mode_move then
|
|
move_component(mem.selected, GRID_SIZE, nil)
|
|
else
|
|
resize_component(mem.selected, GRID_SIZE, nil)
|
|
end
|
|
end,
|
|
toggle_size_move = function()
|
|
mem.mode_move = not mem.mode_move
|
|
end,
|
|
toggle_grid_size = function()
|
|
GRID_SIZE = GRID_SIZE < 1.6 and GRID_SIZE + 0.4 or 0.4
|
|
mem.GRID_SIZE = GRID_SIZE
|
|
end,
|
|
delete = function()
|
|
if mem.selected.ref then
|
|
local name = mem.selected.ref.name
|
|
local id = mem.workspace_search[name]
|
|
mem.workspace[id] = nil
|
|
workspace_cleanup()
|
|
deselect()
|
|
end
|
|
end,
|
|
component_type = function(data)
|
|
local component_type_idx = textlist_indexof(data.component_type)
|
|
mem.component_type = COMPONENT_TYPES[component_type_idx]
|
|
mem.toolbar[7].selected_id = component_type_idx
|
|
end,
|
|
create = function(data)
|
|
local name = create_component_name(mem.component_type, data.component_name)
|
|
if name then
|
|
local component = create_component(mem.component_type, name)
|
|
table.insert(mem.workspace, component)
|
|
mem.workspace_search[component.name] = table.maxn(mem.workspace)
|
|
if not SELECTABLE_COMPONENTS[mem.component_type] then
|
|
-- Add control anchor button to allow passive component selection
|
|
local control = create_control_component(component)
|
|
table.insert(mem.workspace, control)
|
|
mem.workspace_control[control.name] = table.maxn(mem.workspace)
|
|
end
|
|
select_component(name)
|
|
end
|
|
end,
|
|
hide_toolbar = function()
|
|
mem.draw_toolbar = not mem.draw_toolbar
|
|
end,
|
|
edit_component = function()
|
|
mem.component_editor_items_idx = 1
|
|
mem.draw_component_editor = not mem.draw_component_editor
|
|
end,
|
|
component_editor_items = function(data)
|
|
mem.component_editor_items_idx = textlist_indexof(data.component_editor_items)
|
|
end,
|
|
component_listelement_add = function(data)
|
|
if mem.selected.ref then
|
|
local items = mem.selected.ref.choices or mem.selected.ref.listelements
|
|
if mem.component_editor_items_idx then
|
|
table.insert(items, mem.component_editor_items_idx + 1, data.component_listelement)
|
|
mem.component_editor_items_idx = mem.component_editor_items_idx + 1
|
|
elseif items then
|
|
table.insert(items, data.component_listelement)
|
|
end
|
|
else
|
|
mem.draw_component_editor = false
|
|
deselect()
|
|
end
|
|
end,
|
|
component_listelement_del = function(data)
|
|
if mem.selected.ref then
|
|
local items = mem.selected.ref.choices or mem.selected.ref.listelements
|
|
if items and mem.component_editor_items_idx then
|
|
table.remove(items, mem.component_editor_items_idx)
|
|
mem.component_editor_items_idx = math.max(1, mem.component_editor_items_idx - 1)
|
|
end
|
|
else
|
|
mem.draw_component_editor = false
|
|
deselect()
|
|
end
|
|
end,
|
|
component_editor_save = function(data)
|
|
if mem.selected.ref then
|
|
if data.component_label then
|
|
mem.selected.ref.label = data.component_label
|
|
end
|
|
if data.component_default then
|
|
mem.selected.ref.default = data.component_default
|
|
end
|
|
if data.component_image then
|
|
mem.selected.ref.image = data.component_image
|
|
end
|
|
end
|
|
mem.draw_component_editor = false
|
|
deselect()
|
|
end,
|
|
lock = function()
|
|
-- toggle lock, maybe add timeout for lock in public version?
|
|
mem.locked = not mem.locked
|
|
end,
|
|
reset = function()
|
|
-- add confirmation message before destroying everything?
|
|
reset()
|
|
end,
|
|
code = function()
|
|
local result = {}
|
|
local vk = { [true] = '="', [false] = '=', }
|
|
local vi = { [true] = '"', [false] = '', }
|
|
local ve = { [true] = '",\n', [false] = ',\n', }
|
|
local labelcleanup = { name = 1, H = 1, W = 1 }
|
|
local indent = 2
|
|
table.insert(result, 'digiline_send("touch",{\n')
|
|
for i,component in ipairs(mem.workspace) do
|
|
if mem.workspace_control[component.name] ~= i then
|
|
local islabel = component.command == 'addlabel' or component.command == 'addvertlabel'
|
|
table.insert(result, (i == 1 and string.rep(' ', indent) or '') .. '{\n')
|
|
indent = indent + 2
|
|
local pre = string.rep(' ', indent)
|
|
local pos = {}
|
|
for k,v in pairs(component) do
|
|
if type(v) == 'table' then
|
|
digiline_send('dbg', 'serializing table ' .. k)
|
|
table.insert(result, string.rep(' ', indent) .. k .. '={\n')
|
|
indent = indent + 2
|
|
pre = string.rep(' ', indent)
|
|
for _,li in ipairs(v) do
|
|
local quote = type(li) == 'string'
|
|
table.insert(result, pre .. vi[quote] .. li .. ve[quote])
|
|
end
|
|
indent = indent - 2
|
|
table.insert(result, string.rep(' ', indent) .. '},')
|
|
elseif k ~= 'type' then
|
|
if k == 'X' or k == 'Y' or k == 'H' or k == 'W' then
|
|
table.insert(pos, k .. '=' .. v .. ',')
|
|
else
|
|
local quote = type(v) == 'string'
|
|
if islabel and labelcleanup[k] then
|
|
-- noop
|
|
elseif k == 'name' then
|
|
table.insert(result, pre .. k .. vk[quote] .. nice_name(v) .. ve[quote])
|
|
else
|
|
table.insert(result, pre .. k .. vk[quote] .. tostring(v) .. ve[quote])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if table.maxn(pos) > 0 then
|
|
table.insert(result, pre .. table.concat(pos, ' ') .. '\n')
|
|
end
|
|
indent = indent - 2
|
|
table.insert(result, string.rep(' ', indent) .. '},')
|
|
end
|
|
end
|
|
table.insert(result, '{X=7.18,label="Created with SX Digi labs Touch Designer",Y=8.11,command="addlabel"}\n})\n')
|
|
mem.code = table.concat(result)
|
|
mem.draw_code = true
|
|
end,
|
|
close_code = function()
|
|
mem.draw_code = false
|
|
end,
|
|
quit = function()
|
|
deselect()
|
|
end,
|
|
}
|
|
|
|
local selectable = function(key)
|
|
-- Hack to get around the fact that touch screen will always populate input fields into incoming data
|
|
-- FIXME somehow, maybe find match from table?
|
|
local m = string.sub(key, 1, 2)
|
|
return m == '_b' or m == '_c' or m == '_i'
|
|
end
|
|
|
|
local execute_event = function(data)
|
|
for key,_ in pairs(data) do
|
|
if selectable(key) then
|
|
select_component(key)
|
|
return true
|
|
elseif functions[key] then
|
|
functions[key](data)
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
if event.type == 'digiline' then
|
|
if not execute_event(event.msg) then
|
|
local str = ''
|
|
for k,v in pairs(event.msg) do
|
|
str = str .. k
|
|
end
|
|
info('Exec failed' .. str)
|
|
end
|
|
elseif event.type == 'program' then
|
|
mem.touch_clear_commands = { command = "clear" }
|
|
elseif event.type == 'interrupt' then
|
|
if not mem.workspace then
|
|
reset()
|
|
end
|
|
end
|
|
|
|
if COMPONENT_TYPES then
|
|
draw_designer()
|
|
else
|
|
initialize_designer()
|
|
interrupt(1)
|
|
end |