To address these issues, I made a very simple window management script to allow labels, miniConsoles and gauges to be positioned and sized any way you wish. You create the item using the normal commands, then add it to the window manager along with what type of item it is, position and size data, and an origin which specifies a corner where you want your position to be determined from. You can then call on new functions to resize, move, or relocate (change origin corners) for any item you have added. When a window resize event occurs, the items are all resized and repositioned automatically. No new objects are created, and you can still use all the normal functions exactly like you would expect.
Here is the code, some simple documentation is provided at the top:
-- Window Manager Script --
-- Zachary Hiland
-- 6/16/2013
--
-- Functions Details
--
-- windowManager.add(name, type, x, y, width, height, origin) or windowManager.add(info_table)
-- adds a window to the windowManager
-- info_table must have a valid entry for each argument, by the same name, as in the normal function call
-- name - name of already created window (label, miniConsole, or gauge)
-- type - identify the type of window, must be label, miniConsole, or gauge
-- x - distance horizontally from the origin corner
-- y - distance vertically from the origin corner
-- width - width of window
-- height - height of window
-- origin - corner to act as origin for this window, must be topleft, topright, bottomleft, or bottomright
-- note: all measurements should be numbers, or strings with values measured in percent or pixels (or unlabeled)
-- if a measurement contains both percent and pixel values (or multiple values of the same type), they should be separated
-- by a "+" symbol. Example: "25% + 50px + 16"
-- important: no negative numbers
--
-- windowManager.remove(name)
-- removes a window from the windowManager
--
-- windowManager.move(name, x, y)
-- moves a window with the windowManager
--
-- windowManager.resize(name, width, height)
-- resizes a window with the windowManager
--
-- windowManager.relocate(name, origin)
-- changes the corner acting as the origin for a window in the windowManager
--
-- windowManager.getValue(name, value)
-- returns the calculated size or position values, or the origin, for a window in the windowManager
--
-- windowManager.math(value1, value2, operation)
-- allows addition and subtraction of measurements with each other,
-- and multiplication and division of a measurement by a normal number
--
-- windowManager.simplify(measurement)
-- returns a simplified version of a measurement (all percent and pixel values are combined together)
--
-- windowManager.refresh(name)
-- sets the size and location of a window in the windowManager using previously set values
-- note: generally this function does not need to be called
--
-- windowManager.refreshAll()
-- note: this function is called automatically when a sysWindowResizeEvent event occurs,
-- and generally does not need to be called manually
windowManager = windowManager or {}
windowManager.list = windowManager.list or {}
local function calcScaledNum(scale,num)
scale_table = string.split(scale," %+ ")
if #scale_table > 2 then
scale = windowManager.simplify(scale)
scale_table = string.split(scale," %+ ")
end
scale = 0
if #scale_table == 2 then
scale = string.cut(scale_table[1],#scale_table[1] - 1) * num / 100
scale = scale + string.gsub(scale_table[2],"px","")
elseif string.find(scale_table[1],"%%") then
scale = string.cut(scale_table[1],#scale_table[1] - 1) * num / 100
else
scale = string.gsub(scale_table[1],"px","")
end
scale = math.floor(scale + 0.5)
return scale
end
function windowManager.simplify(measure)
measure = string.gsub(measure,"([^%s%+%-]+)%s*-%s*([%d%-]+)","%1 + -%2")
measure = string.gsub(measure,"%-%-","")
local measure_table = string.split(measure,"+")
local percent, pixel = 0,0
for k,v in ipairs(measure_table) do
v = string.trim(v)
if string.find(v,"%%") then
v = string.gsub(v,"%%","")
percent = percent + v
else
v = string.gsub(v,"px","")
pixel = pixel + v
end
end
percent = math.floor(1000 * percent + .5) / 1000
pixel = math.floor(1000 * pixel + .5) / 1000
if percent == 0 then
measure = pixel .. "px"
elseif pixel == 0 then
measure = percent .. "%"
else
measure = percent .. "% + " .. pixel .. "px"
end
return measure
end
function windowManager.math(measure,num,op)
assert(table.contains({"multiply","divide", "add", "subtract"},op),"windowManager.math: bad argument #3 \"operation\", must be multiply or divide")
if op == "divide" or op == "multiply" then
if string.find(num,"%%") then
num = string.gsub(num,"%%","") / 100
end
num = assert(tonumber(num),"windowManager.math: bad argument #2 \"num\", must be a number")
measure = string.gsub(measure,"([^%s%+%-]+)%s*-%s*([%d%-]+)","%1 + -%2")
local measure_table = string.split(measure,"+")
if op == "divide" then num = 1 / num end
for k,v in ipairs(measure_table) do
v = string.trim(v)
v = (string.gsub(v,"(%d+).*","%1") * num) .. string.gsub(v,".*%d+(.*)","%1")
measure_table[k] = v
end
measure = table.concat(measure_table," + ")
else
if op == "add" then
measure = measure .. " + " .. num
elseif op == "subtract" then
measure = measure .. " + -" .. num
end
measure = string.gsub(measure,"([^%s%+%-]+)%s*-%s*([%d%-]+)","%1 + -%2")
end
return windowManager.simplify(measure)
end
function windowManager.add(name, window_type, x, y, w, h, origin)
local tbl = {}
if type(name) == "table" then
tbl = table.update(tbl,name)
name = tbl.name
x = tbl.x
y = tbl.y
w = tbl.width
h = tbl.height
origin = tbl.origin
window_type = tbl.type
tbl = {}
end
assert(name, "windowManager.add: bad argument #1 \"name\".")
windowManager.list[name] = nil
assert(type(window_type) == "string", "windowManager.add: bad argument #2 \"type\", must be string.")
window_type = string.lower(window_type)
assert(table.contains({"label","miniconsole","gauge"},window_type), "windowManager.add: invalid type")
assert(x and y and w and h, "windowManager.add: must have x, y, width, and height.")
origin = origin or "topleft"
origin = string.lower(origin)
assert(table.contains({"topleft","topright","bottomleft","bottomright"},origin),"windowManager.add: bad argument #7 \"origin\".")
x = windowManager.simplify(x)
y = windowManager.simplify(y)
w = windowManager.simplify(w)
h = windowManager.simplify(h)
tbl = {
type = window_type,
x = x, y = y, h = h, w = w,
origin = origin}
windowManager.list[name] = tbl
windowManager.refresh(name)
end
function windowManager.remove(name)
windowManager.list[name] = nil
end
function windowManager.refresh(name, main_w, main_h)
local info = assert(windowManager.list[name], "windowManager.refresh: no such window.")
local x,y,w,h,origin,win_type = info.x, info.y, info.w, info.h, info.origin, info.type
if not (main_w and main_h) then
main_w, main_h = getMainWindowSize()
end
w = calcScaledNum(w,main_w)
x = calcScaledNum(x,main_w)
h = calcScaledNum(h,main_h)
y = calcScaledNum(y,main_h)
if string.find(origin,"right") then
x = main_w - x - w
end
if string.find(origin,"bottom") then
y = main_h - y - h
end
if win_type ~= "gauge" then
moveWindow(name,x,y)
resizeWindow(name,w,h)
else
moveGauge(name,x,y)
resizeGauge(name,w,h)
end
end
function windowManager.resize(name, w, h)
assert(windowManager.list[name], "windowManager.resize: no such window.")
assert(w and h, "windowManager.resize: must have both width and height.")
w = windowManager.simplify(w)
h = windowManager.simplify(h)
windowManager.list[name].w = w
windowManager.list[name].h = h
windowManager.refresh(name)
end
function windowManager.move(name, x, y)
assert(windowManager.list[name], "windowManager.move: no such window.")
assert(x and y, "windowManager.move: must have both x and y.")
x = windowManager.simplify(x)
y = windowManager.simplify(y)
windowManager.list[name].x = x
windowManager.list[name].y = y
windowManager.refresh(name)
end
function windowManager.relocate(name, origin)
assert(windowManager.list[name], "windowManager.relocate: no such window.")
origin = origin or "topleft"
origin = string.lower(origin)
assert(table.contains({"topleft","topright","bottomleft","bottomright"},origin),"windowManager.relocate: bad argument #2 \"origin\".")
windowManager.list[name].origin = origin
windowManager.refresh(name)
end
function windowManager.getValue(name, value)
assert(windowManager.list[name], "windowManager.getValue: no such window.")
assert(table.contains({"x","y","width","height","w","h","origin"},value),"windowManager.getValue: no such value.")
local sys_w, sys_h = getMainWindowSize()
if value == "width" then value = "w" end
if value == "height" then value = "h" end
local tmp = windowManager.list[name][value]
if value == "w" or value == "x" then
tmp = calcScaledNum(tmp,sys_w)
elseif value == "h" or value == "y" then
tmp = calcScaledNum(tmp,sys_h)
end
return tmp
end
function windowManager.refreshAll()
local main_w, main_h = getMainWindowSize()
for k,v in pairs(windowManager.list) do
windowManager.refresh(k, main_w, main_h)
end
end
registerAnonymousEventHandler("sysWindowResizeEvent", "windowManager.refreshAll")