Squashed 'core/' content from commit 455d15f

git-subtree-dir: core
git-subtree-split: 455d15f24a60bad013d07712457318e45885de75
This commit is contained in:
petrucci4prez 2016-08-11 23:50:45 -04:00
commit fd9244d4eb
25 changed files with 2569 additions and 0 deletions

245
func/json.lua Normal file
View File

@ -0,0 +1,245 @@
local c = {}
local _STRING_GSUB = string.gsub
local _STRING_CHAR = string.char
local _STRING_FIND = string.find
local _STRING_SUB = string.sub
local _TABLE_CONCAT = table.concat
local _MATH_FLOOR = math.floor
local _PAIRS = pairs
local _TONUMBER = tonumber
local decode -- to ref this before definition
local decode_scanWhitespace = function(s, startPos)
local whitespace = " \n\r\t"
local stringLen = #s
while (_STRING_FIND(whitespace, _STRING_SUB(s, startPos, startPos), 1, true) and
startPos <= stringLen) do
startPos = startPos + 1
end
return startPos
end
local decode_scanArray = function(s, startPos)
local array = {}
local stringLen = #s
--~ assert(_STRING_SUB(s, startPos, startPos) == '[',
--~ 'decode_scanArray called but array does not start at position ' .. startPos ..
--~ ' in string:\n'..s )
startPos = startPos + 1
repeat
startPos = decode_scanWhitespace(s, startPos)
--~ assert(startPos <= stringLen, 'JSON String ended unexpectedly scanning array.')
local curChar = _STRING_SUB(s,startPos,startPos)
if (curChar == ']') then
return array, startPos + 1
end
if (curChar == ',') then
startPos = decode_scanWhitespace(s, startPos + 1)
end
--~ assert(startPos <= stringLen, 'JSON String ended unexpectedly scanning array.')
object, startPos = decode(s, startPos)
array[#array + 1] = object
until false
end
local decode_scanComment = function(s, startPos)
--~ assert(_STRING_SUB(s, startPos, startPos + 1) == '/*',
--~ "decode_scanComment called but comment does not start at position " .. startPos)
local endPos = _STRING_FIND(s, '*/', startPos + 2)
--~ assert(endPos ~= nil, "Unterminated comment in string at " .. startPos)
return endPos + 2
end
local decode_scanConstant = function(s, startPos)
local consts = {["true"] = true, ["false"] = false, ["null"] = nil}
local constNames = {"true", "false", "null"}
for _, k in _PAIRS(constNames) do
if _STRING_SUB(s, startPos, startPos + #k - 1 ) == k then
return consts[k], startPos + #k
end
end
--~ assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' ..
--~ startPos)
end
local decode_scanNumber = function(s, startPos)
local endPos = startPos + 1
local stringLen = #s
local acceptableChars = "+-0123456789.e"
while (_STRING_FIND(acceptableChars, _STRING_SUB(s, endPos, endPos), 1, true)
and endPos <= stringLen) do
endPos = endPos + 1
end
local numberString = _STRING_GSUB(_STRING_SUB(s, startPos, endPos - 1), '+', '')
return _TONUMBER(numberString), endPos
end
local decode_scanObject = function(s, startPos)
local object = {}
local stringLen = #s
local key, value
--~ assert(_STRING_SUB(s, startPos, startPos) == '{',
--~ 'decode_scanObject called but object does not start at position ' .. startPos ..
--~ ' in string:\n' .. s)
startPos = startPos + 1
repeat
startPos = decode_scanWhitespace(s, startPos)
--~ assert(startPos <= stringLen, 'JSON string ended unexpectedly while scanning object.')
local curChar = _STRING_SUB(s, startPos, startPos)
if (curChar == '}') then
return object, startPos + 1
end
if (curChar == ',') then
startPos = decode_scanWhitespace(s, startPos + 1)
end
--~ assert(startPos <= stringLen, 'JSON string ended unexpectedly scanning object.')
-- Scan the key
key, startPos = decode(s, startPos)
--~ assert(startPos <= stringLen,
--~ 'JSON string ended unexpectedly searching for value of key ' .. key)
startPos = decode_scanWhitespace(s, startPos)
--~ assert(startPos <= stringLen,
--~ 'JSON string ended unexpectedly searching for value of key ' .. key)
--~ assert(_STRING_SUB(s, startPos, startPos) == ':',
--~ 'JSON object key-value assignment mal-formed at ' .. startPos)
startPos = decode_scanWhitespace(s, startPos + 1)
--~ assert(startPos <= stringLen,
--~ 'JSON string ended unexpectedly searching for value of key ' .. key)
value, startPos = decode(s, startPos)
object[key] = value
until false
end
local escapeSequences = {
["\\t"] = "\t",
["\\f"] = "\f",
["\\r"] = "\r",
["\\n"] = "\n",
["\\b"] = "\b"
}
setmetatable(escapeSequences, {__index = function(t, k) return _STRING_SUB(k, 2) end})--skip "\"
local decode_scanString = function (s, startPos)
--~ assert(startPos, 'decode_scanString(..) called without start position')
local startChar = _STRING_SUB(s, startPos, startPos)
--~ assert(startChar == [["]] or startChar == [[']],
--~ 'decode_scanString called for a non-string')
local t = {}
local i, j = startPos, startPos
while _STRING_FIND(s, startChar, j + 1) ~= j + 1 do
local oldj = j
local x, y = _STRING_FIND(s, startChar, oldj + 1)
i, j = _STRING_FIND(s, "\\.", j + 1)
if not i or x < i then i, j = x, y - 1 end
--~ table.insert(t, _STRING_SUB(s, oldj + 1, i - 1))
t[#t + 1] = _STRING_SUB(s, oldj + 1, i - 1)
if _STRING_SUB(s, i, j) == "\\u" then
local a = _STRING_SUB(s, j + 1, j + 4)
local n = _TONUMBER(a, 16)
local x
j = j + 4
--~ assert(n, "String decoding failed: bad Unicode escape " .. a .. " at position " ..
--~ i .. " : " .. j)
if n < 0x80 then
x = _STRING_CHAR(n % 0x80)
elseif n < 0x800 then
x = _STRING_CHAR(0xC0 + (_MATH_FLOOR(n / 64) % 0x20), 0x80 + (n % 0x40))
else
x = _STRING_CHAR(0xE0 + (_MATH_FLOOR(n / 4096) % 0x10), 0x80 +
(_MATH_FLOOR(n / 64) % 0x40), 0x80 + (n % 0x40))
end
--~ table.insert(t, x)
t[#t + 1] = x
else
--~ table.insert(t, escapeSequences[_STRING_SUB(s, i, j)])
t[#t + 1] = escapeSequences[_STRING_SUB(s, i, j)]
end
end
--~ table.insert(t, _STRING_SUB(j, j + 1))
t[#t + 1] = _STRING_SUB(j, j + 1)
--~ assert(_STRING_FIND(s, startChar, j + 1), "String decoding failed: missing closing " ..
--~ startChar .. " at position " .. j .. "(for string at position " .. startPos .. ")")
return _TABLE_CONCAT(t, ""), j + 2
end
decode = function(s, startPos)
startPos = startPos or 1
startPos = decode_scanWhitespace(s, startPos)
--~ assert(startPos <= #s,
--~ 'Unterminated JSON encoded object found at position in [' .. s .. ']')
local curChar = _STRING_SUB(s, startPos, startPos)
if curChar == '{' then
return decode_scanObject(s, startPos)
end
if curChar == '[' then
return decode_scanArray(s, startPos)
end
if _STRING_FIND("+-0123456789.e", curChar, 1, true) then
return decode_scanNumber(s, startPos)
end
if curChar == [["]] or curChar == [[']] then
return decode_scanString(s, startPos)
end
if _STRING_SUB(s, startPos, startPos + 1) == '/*' then
return decode(s, decode_scanComment(s, startPos))
end
return decode_scanConstant(s, startPos)
end
c.decode = decode
return c

176
func/util.lua Normal file
View File

@ -0,0 +1,176 @@
local c = {}
local _PAIRS = pairs
local _TYPE = type
local _TONUMBER = tonumber
local _TOSTRING = tostring
local _IO_POPEN = io.popen
local _IO_OPEN = io.open
local _MATH_FLOOR = math.floor
local _MATH_CEIL = math.ceil
local _STRING_SUB = string.sub
local _STRING_GSUB = string.gsub
local _STRING_MATCH = string.match
local _STRING_FORMAT = string.format
local _STRING_UPPER = string.upper
local _CONKY_PARSE = conky_parse
local _SELECT = select
local _SETMETATABLE = setmetatable
local copy_table = function(t)
local s = {}
for i, v in _PAIRS(t) do s[i] = _TYPE(v) == 'table' and copy_table(v) or v end
return s
end
local round = function(x, places)
local m = 10 ^ (places or 0)
if x >= 0 then
return _MATH_FLOOR(x * m + 0.5) / m
else
return _MATH_CEIL(x * m - 0.5) / m
end
end
local get_bytes_power = function(unit)
if unit == 'KiB' then return 10
elseif unit == 'MiB' then return 20
elseif unit == 'GiB' then return 30
elseif unit == 'TiB' then return 40
else return 0
end
end
local convert_bytes = function(x, old_unit, new_unit)
if old_unit == new_unit then
return _TONUMBER(x)
else
return x * 2 ^ (get_bytes_power(old_unit) - get_bytes_power(new_unit))
end
end
local round_to_string = function(x, places)
places = places or 0
local y = round(x, places)
if places > 0 then return _STRING_FORMAT('%.'..places..'f', y) else return _TOSTRING(y) end
end
local precision_round_to_string = function(x, sig_fig)
sig_fig = sig_fig or 4
if x < 10 then return round_to_string(x, sig_fig - 1)
elseif x < 100 then return round_to_string(x, sig_fig - 2)
elseif x < 1000 then return round_to_string(x, sig_fig - 3)
else return round_to_string(x, sig_fig - 4)
end
end
local read_entire_file = function(file, regex, mode)
if not file then return '' end
local str = file:read(mode or '*a')
file:close()
if not str then return '' end
if regex then return _STRING_MATCH(str, regex) or '' else return str end
end
local conky = function(expr, regex)
local ans = _CONKY_PARSE(expr)
if regex then return _STRING_MATCH(ans, regex) or '' else return ans end
end
local precision_convert_bytes = function(val, old_unit, new_unit, sig_fig)
return precision_round_to_string(convert_bytes(val, old_unit, new_unit), sig_fig)
end
local get_unit = function(bytes)
if bytes < 1024 then return 'B'
elseif bytes < 1048576 then return 'KiB'
elseif bytes < 1073741824 then return 'MiB'
else return 'GiB'
end
end
local get_unit_base_K = function(kilobytes)
if kilobytes < 1024 then return 'KiB'
elseif kilobytes < 1048576 then return 'MiB'
elseif kilobytes < 1073741824 then return 'GiB'
else return 'TiB'
end
end
local parse_unit = function(str)
return _STRING_MATCH(str, '^([%d%p]-)(%a+)')
end
local char_count = function(str, char)
return _SELECT(2, _STRING_GSUB(str, char, char))
end
local line_count = function(str)
return char_count(str, '\n')
end
local execute_cmd = function(cmd, regex, mode)
return read_entire_file(_IO_POPEN(cmd), regex, mode)
end
local read_file = function(path, regex, mode)
return read_entire_file(_IO_OPEN(path, 'rb'), regex, mode)
end
local write_file = function(path, str)
local file = _IO_OPEN(path, 'w+')
if file then
file:write(str)
file:close()
end
end
local conky_numeric = function(expr, regex)
return _TONUMBER(conky(expr, regex)) or 0
end
local memoize = function(f)
local mem = {} -- memoizing table
_SETMETATABLE(mem, {__mode = "kv"}) -- make it weak
return function (x) -- new version of f, with memoizing
local r = mem[x]
if not r then -- no previous result?
r = f(x) -- calls original function
mem[x] = r -- store result for reuse
end
return r
end
end
local convert_unix_time = function(unix_time, frmt)
local cmd = 'date -d @'..unix_time
if frmt then cmd = cmd..' +\''..frmt..'\'' end
return _STRING_MATCH(execute_cmd(cmd), '(.-)\n')
end
local capitalize_each_word = function(str)
return _STRING_SUB(_STRING_GSUB(" "..str, "%W%l", _STRING_UPPER), 2)
end
c.round = round
c.get_bytes_power = get_bytes_power
c.convert_bytes = convert_bytes
c.copy_table = copy_table
c.conky = conky
c.round_to_string = round_to_string
c.precision_round_to_string = precision_round_to_string
c.precision_convert_bytes = precision_convert_bytes
c.get_unit = get_unit
c.get_unit_base_K = get_unit_base_K
c.parse_unit = parse_unit
c.char_count = char_count
c.line_count = line_count
c.execute_cmd = execute_cmd
c.read_file = read_file
c.write_file = write_file
c.conky_numeric = conky_numeric
c.memoize = memoize
c.convert_unix_time = convert_unix_time
c.capitalize_each_word = capitalize_each_word
return c

55
super/Color.lua Normal file
View File

@ -0,0 +1,55 @@
local c = {}
local Gradient = require 'Gradient'
local _CAIRO_PATTERN_CREATE_RGBA = cairo_pattern_create_rgba
--Color(hex_rgba, [force_alpha])
local init = function(arg)
local hex_rgba = arg.hex_rgba
local obj = {
r = ((hex_rgba / 0x1000000) % 0x100) / 255.,
g = ((hex_rgba / 0x10000) % 0x100) / 255.,
b = ((hex_rgba / 0x100) % 0x100) / 255.,
a = arg.force_alpha or (hex_rgba % 0x100) / 255.
}
obj.userdata = _CAIRO_PATTERN_CREATE_RGBA(obj.r, obj.g, obj.b, obj.a)
return obj
end
--ColorStop(hex_rgba, stop, [force_alpha])
local initColorStop = function(arg)
local obj = init{
hex_rgba = arg.hex_rgba,
force_alpha = arg.force_alpha
}
obj.stop = arg.stop
return obj
end
--Gradient([p1], [p2], [r0], [r1], ... color stops)
local initGradient = function(arg)
local obj = {
color_stops = {},
ptype = 'Gradient'
}
for i = 1, #arg do obj.color_stops[i] = arg[i] end
Gradient(obj, arg.p1, arg.p2, arg.r1, arg.r2)
return obj
end
c.init = init
c.ColorStop = initColorStop
c.Gradient = initGradient
return c

20
super/Gradient.lua Normal file
View File

@ -0,0 +1,20 @@
local _CAIRO_PATTERN_CREATE_RADIAL = cairo_pattern_create_radial
local _CAIRO_PATTERN_CREATE_LINEAR = cairo_pattern_create_linear
local _CAIRO_PATTERN_ADD_COLOR_STOP_RGBA = cairo_pattern_add_color_stop_rgba
local _PAIRS = pairs
local set_dimensions = function(gradient, p1, p2, r1, r2)
if p1 and p2 then
local pattern = (r1 and r2) and
_CAIRO_PATTERN_CREATE_RADIAL(p1.x, p1.y, r1, p2.x, p2.y, r2) or
_CAIRO_PATTERN_CREATE_LINEAR(p1.x, p1.y, p2.x, p2.y)
for _, color_stop in _PAIRS(gradient.color_stops) do
_CAIRO_PATTERN_ADD_COLOR_STOP_RGBA(pattern, color_stop.stop, color_stop.r,
color_stop.g, color_stop.b, color_stop.a)
end
gradient.userdata = pattern
end
end
return set_dimensions

58
super/Super.lua Normal file
View File

@ -0,0 +1,58 @@
local c = {}
local Gradient = require 'Gradient'
local schema = require 'default_patterns'
local _TONUMBER = tonumber
local _STRING_SUB = string.sub
--Pattern(pattern, [p1], [p2], [r1], [r2], [key])
local initPattern = function(arg)
local pattern = arg.pattern
local p1 = arg.p1
local p2 = arg.p2
local r1 = arg.r1
local r2 = arg.r2
if p1 and p2 and pattern and pattern.ptype == 'Gradient' then
Gradient(pattern, p1, p2, r1, r2)
end
return pattern.userdata
end
--Critical([critical_pattern], [critical_limit], [p1], [p2], [r1], [r2])
local CRITICAL_PATTERN = schema.red
local CRITICAL_LIMIT = '>80'
local CRITICAL_CREATE_FUNCTION = function(limit)
local compare = limit and _STRING_SUB(limit, 1, 1)
local value = limit and _TONUMBER(_STRING_SUB(limit, 2))
if compare == '>' then return function(n) return (n > value) end end
if compare == '<' then return function(n) return (n < value) end end
return function(n) return nil end --if no limit then return dummy
end
local initCritical = function(arg)
local obj = {
source = initPattern{
pattern = arg.critical_pattern or CRITICAL_PATTERN,
p1 = arg.p1,
p2 = arg.p2,
r1 = arg.r1,
r2 = arg.r2,
},
enabled = CRITICAL_CREATE_FUNCTION(arg.critical_limit or CRITICAL_LIMIT)
}
return obj
end
c.Pattern = initPattern
c.Critical = initCritical
return c

1112
super/Widget.lua Normal file

File diff suppressed because it is too large Load Diff

5
widget/CR.lua Normal file
View File

@ -0,0 +1,5 @@
local cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1366, 768)
local CR = cairo_create(cs)
cairo_surface_destroy(cs)
return CR

31
widget/arc/Arc.lua Normal file
View File

@ -0,0 +1,31 @@
local c = {}
local _CR = require 'CR'
local _CAIRO_NEW_PATH = cairo_new_path
local _CAIRO_ARC = cairo_arc
local _CAIRO_COPY_PATH = cairo_copy_path
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local draw = function(obj, cr)
_CAIRO_APPEND_PATH(cr, obj.path)
_CAIRO_SET_LINE_WIDTH(cr, obj.thickness)
_CAIRO_SET_LINE_CAP(cr, obj.cap)
_CAIRO_SET_SOURCE(cr, obj.source)
_CAIRO_STROKE(cr)
end
local create_path = function(x, y, radius, theta0, theta1)
_CAIRO_NEW_PATH(_CR)
_CAIRO_ARC(_CR, x, y, radius, theta0, theta1)
return _CAIRO_COPY_PATH(_CR)
end
c.draw = draw
c.create_path = create_path
return c

View File

@ -0,0 +1,34 @@
local c = {}
local Dial = require 'Dial'
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local _CAIRO_APPEND_PATH = cairo_append_path
local set = function(obj, index, percent)
Dial.set(obj.dials[index], percent)
end
local draw = function(obj, cr)
local dials = obj.dials
_CAIRO_SET_LINE_WIDTH(cr, dials[1].thickness)
_CAIRO_SET_LINE_CAP(cr, dials[1].cap)
for i = 1, #dials do
local current_dial = dials[i]
_CAIRO_SET_SOURCE(cr, current_dial.source)
_CAIRO_APPEND_PATH(cr, current_dial.path)
_CAIRO_STROKE(cr)
_CAIRO_SET_SOURCE(cr, current_dial.current_source)
_CAIRO_APPEND_PATH(cr, current_dial.dial_path)
_CAIRO_STROKE(cr)
end
end
c.set = set
c.draw = draw
return c

30
widget/arc/Dial.lua Normal file
View File

@ -0,0 +1,30 @@
local c = {}
local Arc = require 'Arc'
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local _CAIRO_APPEND_PATH = cairo_append_path
local set = function(obj, percent)
obj.percent = percent
obj.dial_path = obj._make_dial_path(percent)
if obj.critical.enabled(obj.percent) then
obj.current_source = obj.critical.source
else
obj.current_source = obj.indicator_source
end
end
local draw = function(obj, cr)
Arc.draw(obj, cr)
_CAIRO_SET_SOURCE(cr, obj.current_source)
_CAIRO_APPEND_PATH(cr, obj.dial_path)
_CAIRO_STROKE(cr)
end
c.set = set
c.draw = draw
return c

31
widget/image/Image.lua Normal file
View File

@ -0,0 +1,31 @@
local c = {}
local _IMLIB_LOAD_IMAGE = imlib_load_image
local _IMLIB_CONTEXT_SET_IMAGE = imlib_context_set_image
local _IMLIB_RENDER_IMAGE_ON_DRAWABLE = imlib_render_image_on_drawable
local _IMLIB_FREE_IMAGE = imlib_free_image
local _IMLIB_IMAGE_GET_WIDTH = imlib_image_get_width
local _IMLIB_IMAGE_GET_HEIGHT = imlib_image_get_height
local set = function(obj, path)
local img = _IMLIB_LOAD_IMAGE(path)
_IMLIB_CONTEXT_SET_IMAGE(img)
obj.width = _IMLIB_IMAGE_GET_WIDTH()
obj.height = _IMLIB_IMAGE_GET_HEIGHT()
obj.path = path
_IMLIB_FREE_IMAGE()
end
local draw = function(obj)
local img = _IMLIB_LOAD_IMAGE(obj.path)
_IMLIB_CONTEXT_SET_IMAGE(img)
_IMLIB_RENDER_IMAGE_ON_DRAWABLE(obj.x, obj.y)
_IMLIB_FREE_IMAGE()
end
c.set = set
c.draw = draw
return c

View File

@ -0,0 +1,31 @@
local c = {}
local _IMLIB_LOAD_IMAGE = imlib_load_image
local _IMLIB_CONTEXT_SET_IMAGE = imlib_context_set_image
local _IMLIB_RENDER_IMAGE_ON_DRAWABLE_AT_SIZE = imlib_render_image_on_drawable_at_size
local _IMLIB_FREE_IMAGE = imlib_free_image
local _IMLIB_IMAGE_GET_WIDTH = imlib_image_get_width
local _IMLIB_IMAGE_GET_HEIGHT = imlib_image_get_height
local set = function(obj, path)
local img = _IMLIB_LOAD_IMAGE(path)
_IMLIB_CONTEXT_SET_IMAGE(img)
obj.img_width = _IMLIB_IMAGE_GET_WIDTH()
obj.img_height = _IMLIB_IMAGE_GET_HEIGHT()
obj.path = path
_IMLIB_FREE_IMAGE()
end
local draw = function(obj)
local img = _IMLIB_LOAD_IMAGE(obj.path)
_IMLIB_CONTEXT_SET_IMAGE(img)
_IMLIB_RENDER_IMAGE_ON_DRAWABLE_AT_SIZE(obj.x, obj.y, obj.width, obj.height)
_IMLIB_FREE_IMAGE()
end
c.set = set
c.draw = draw
return c

110
widget/plot/LabelPlot.lua Normal file
View File

@ -0,0 +1,110 @@
local c = {}
local Plot = require 'Plot'
local Text = require 'Text'
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_SET_FONT_FACE = cairo_set_font_face
local _CAIRO_SET_FONT_SIZE = cairo_set_font_size
local _CAIRO_MOVE_TO = cairo_move_to
local _CAIRO_SHOW_TEXT = cairo_show_text
local _CAIRO_STROKE = cairo_stroke
local X_LABEL_PAD = 8
local Y_LABEL_PAD = 5
local draw = function(obj, cr)
local labels_x = obj.labels.x
local labels_y = obj.labels.y
local labels_x_1 = labels_x[1]
_CAIRO_SET_FONT_FACE(cr, labels_x_1.font_face)
_CAIRO_SET_FONT_SIZE(cr, labels_x_1.font_size)
_CAIRO_SET_SOURCE(cr, labels_x_1.source)
for i = 1, #labels_x do
local current_label = labels_x[i]
_CAIRO_MOVE_TO(cr, current_label.x, current_label.y)
_CAIRO_SHOW_TEXT(cr, current_label.text)
end
for i = 1, #labels_y do
local current_label = labels_y[i]
_CAIRO_MOVE_TO(cr, current_label.x, current_label.y)
_CAIRO_SHOW_TEXT(cr, current_label.text)
end
Plot.draw(obj.plot, cr)
end
local populate_x_labels = function(obj, cr, input_factor)
local labels_x = obj.labels.x
local n = #labels_x - 1
input_factor = input_factor or 1
for i = 0, n do
Text.set(labels_x[i + 1], cr, labels_x._func(input_factor * i / n))
end
labels_x.height = labels_x[1].height + X_LABEL_PAD
local plot = obj.plot
plot.height = obj.height - labels_x.height
plot.bottom_y = plot.height - plot.y
end
local __get_y_axis_width = function(obj)
local labels_y = obj.labels.y
local width = labels_y[1].width
for i = 2, #labels_y do
local current_width = labels_y[i].width
if current_width > width then
width = current_width
end
end
return width + Y_LABEL_PAD
end
local populate_y_labels = function(obj, cr, input_factor)
local labels_y = obj.labels.y
local n = #labels_y - 1
input_factor = input_factor or 1
for i = 0, n do
Text.set(labels_y[i + 1], cr, labels_y._func(input_factor * (n - i) / n))
end
labels_y.width = __get_y_axis_width(obj)
local plot = obj.plot
plot.x = obj.x + labels_y.width
plot.width = obj.width - labels_y.width
end
local position_x_labels = function(obj)
local start_x = obj.plot.x
local labels_x = obj.labels.x
local x_intrvl_width = obj.plot.width / (#labels_x - 1)
for i = 1, #labels_x do
Text.move_to_x(labels_x[i], start_x + x_intrvl_width * (i - 1))
end
end
local position_y_labels = function(obj)
local labels_y = obj.labels.y
local y_intrvl_height = obj.plot.height / (#labels_y - 1)
for i = 1, #labels_y do
Text.move_to_y(labels_y[i], obj.y + y_intrvl_height * (i - 1))
end
end
local update = function(obj, value)
Plot.update(obj.plot, value)
end
c.update = update
c.draw = draw
c.position_x_intrvls = Plot.position_x_intrvls
c.position_y_intrvls = Plot.position_y_intrvls
c.position_graph_outline = Plot.position_graph_outline
c.populate_x_labels = populate_x_labels
c.populate_y_labels = populate_y_labels
c.position_x_labels = position_x_labels
c.position_y_labels = position_y_labels
return c

147
widget/plot/Plot.lua Normal file
View File

@ -0,0 +1,147 @@
local c = {}
local Poly = require 'Poly'
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_MOVE_TO = cairo_move_to
local _CAIRO_LINE_TO = cairo_line_to
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_SET_LINE_JOIN = cairo_set_line_join
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_FILL_PRESERVE = cairo_fill_preserve
local _CAIRO_STROKE = cairo_stroke
local _CAIRO_PATH_DESTROY = cairo_path_destroy
local _TABLE_INSERT = table.insert
local DATA_THICKNESS = 1
local DATA_CAP = CAIRO_LINE_CAP_BUTT
local DATA_JOIN = CAIRO_LINE_JOIN_MITER
local INTRVL_THICKNESS = 1
local INTRVL_CAP = CAIRO_LINE_CAP_BUTT
local OUTLINE_THICKNESS = 2
local OUTLINE_CAP = CAIRO_LINE_CAP_BUTT
local OUTLINE_JOIN = CAIRO_LINE_JOIN_MITER
local update = function(obj, value)
local data = obj.data
_TABLE_INSERT(data, 1, obj.y + obj.height * (1 - value))
if #data == data.n + 2 then data[#data] = nil end
end
local draw = function(obj, cr)
--draw intervals
local intrvls = obj.intrvls
local x_intrvls = intrvls.x
local y_intrvls = intrvls.y
_CAIRO_SET_LINE_WIDTH(cr, INTRVL_THICKNESS)
_CAIRO_SET_LINE_CAP(cr, INTRVL_CAP)
_CAIRO_SET_SOURCE(cr, intrvls.source)
for i = 1, #x_intrvls do
_CAIRO_APPEND_PATH(cr, x_intrvls[i])
end
for i = 1, #y_intrvls do
_CAIRO_APPEND_PATH(cr, y_intrvls[i])
end
_CAIRO_STROKE(cr)
--draw data on graph
local data = obj.data
local n = #data - 1
local spacing = obj.width / data.n
local right = obj.x + obj.width
_CAIRO_MOVE_TO(cr, right, data[1])
for i = 1, n do
_CAIRO_LINE_TO(cr, right - i * spacing, data[i+1])
end
if data.fill_source then
local bottom = obj.y + obj.height
_CAIRO_LINE_TO(cr, right - n * spacing, bottom)
_CAIRO_LINE_TO(cr, right, bottom)
_CAIRO_SET_SOURCE(cr, data.fill_source)
_CAIRO_FILL_PRESERVE(cr)
end
_CAIRO_SET_LINE_WIDTH (cr, DATA_THICKNESS)
_CAIRO_SET_LINE_CAP(cr, DATA_CAP)
_CAIRO_SET_LINE_JOIN(cr, DATA_JOIN)
_CAIRO_SET_SOURCE(cr, data.line_source)
_CAIRO_STROKE(cr)
--draw graph outline (goes on top of everything)
local outline = obj.outline
_CAIRO_APPEND_PATH(cr, outline.path)
_CAIRO_SET_LINE_WIDTH(cr, OUTLINE_THICKNESS)
_CAIRO_SET_LINE_JOIN(cr, OUTLINE_JOIN)
_CAIRO_SET_LINE_CAP(cr, OUTLINE_CAP)
_CAIRO_SET_SOURCE(cr, outline.source)
_CAIRO_STROKE(cr)
end
local position_x_intrvls = function(obj)
local y1 = obj.y - 0.5
local y2 = y1 + obj.height-- + 0.5
local x_intrvls = obj.intrvls.x
local intrvl_width = obj.width / x_intrvls.n
local p1 = {x = 0, y = 0}
local p2 = {x = 0, y = 0}
local obj_x = obj.x
for i = 1, x_intrvls.n do
local x1 = obj_x + intrvl_width * i-- + 0.5
p1.x = x1
p1.y = y1
p2.x = x1
p2.y = y2
_CAIRO_PATH_DESTROY(x_intrvls[i])
x_intrvls[i] = Poly.create_path(nil, p1, p2)
end
end
local position_y_intrvls = function(obj)
local x1 = obj.x-- + 0.5
local x2 = obj.x + obj.width-- + 0.5
local y_intrvls = obj.intrvls.y
local y_intrvl_height = obj.height / y_intrvls.n
local p1 = {x = 0, y = 0}
local p2 = {x = 0, y = 0}
for i = 1, y_intrvls.n do
local y1 = obj.y + (i - 1) * y_intrvl_height - 0.5
p1.x = x1
p1.y = y1
p2.x = x2
p2.y = y1
_CAIRO_PATH_DESTROY(y_intrvls[i])
y_intrvls[i] = Poly.create_path(nil, p1, p2)
end
end
local position_graph_outline = function(obj)
local x1 = obj.x
local y1 = obj.y - 0.5
local x2 = obj.x + obj.width + 0.5
local y2 = obj.y + obj.height + 1.0
local p1 = {x = x1, y = y1}
local p2 = {x = x1, y = y2}
local p3 = {x = x2, y = y2}
_CAIRO_PATH_DESTROY(obj.outline.path)
obj.outline.path = Poly.create_path(nil, p1, p2, p3)
end
c.draw = draw
c.update = update
c.position_x_intrvls = position_x_intrvls
c.position_y_intrvls = position_y_intrvls
c.position_graph_outline = position_graph_outline
return c

89
widget/plot/ScalePlot.lua Normal file
View File

@ -0,0 +1,89 @@
local c = {}
local LabelPlot = require 'LabelPlot'
local _TABLE_INSERT = table.insert
local _TABLE_REMOVE = table.remove
local __scale_data = function(obj, cr, new_domain, new_factor)
local y = obj.y
local current_factor = obj.scale.factor
local data = obj.plot.data
local h = obj.plot.height
for i = 1, #data do
data[i] = y + h * (1 - (1 - (data[i] - y) / h) * (new_factor / current_factor))
end
obj.scale.domain = new_domain
obj.scale.factor = new_factor
LabelPlot.populate_y_labels(obj, cr, 1 / new_factor)
LabelPlot.position_x_labels(obj)
LabelPlot.position_x_intrvls(obj.plot)
LabelPlot.position_y_intrvls(obj.plot)
LabelPlot.position_graph_outline(obj.plot)
end
local update = function(obj, cr, value)
local scale = obj.scale
local new_domain, new_factor = obj.scale._func(value)
--###tick/tock timers
local timers = scale.timers
local n = #timers
for i = n, 1, -1 do
local current_timer = timers[i]
current_timer.remaining = current_timer.remaining - 1
if current_timer.remaining == 0 then
_TABLE_REMOVE(timers, i)
n = n - 1
end
end
--###create/destroy timers
if new_domain > scale.previous_domain then --zap all timers less than/equal to s
for i = n, 1, -1 do
if timers[i].domain <= new_domain then
_TABLE_REMOVE(timers, i)
n = n - 1
end
end
elseif new_domain < scale.previous_domain then --create new timer for prev_s
timers[n + 1] = {
domain = scale.previous_domain,
factor = scale.previous_factor,
remaining = obj.plot.data.n
}
n = n + 1
end
--###scale data
if new_domain > scale.domain then --scale up
__scale_data(obj, cr, new_domain, new_factor)
elseif new_domain < scale.domain then --check timers
if n == 0 then --scale down bc no timers to block
__scale_data(obj, cr, new_domain, new_factor)
elseif scale.timers[1].domain < scale.domain then --scale down to active timer
__scale_data(obj, cr, scale.timers[1].domain, scale.timers[1].factor)
end
end
scale.previous_domain = new_domain
scale.previous_factor = new_factor
local data = obj.plot.data
_TABLE_INSERT(data, 1, obj.y + obj.plot.height * (1 - value * scale.factor))
if #data == data.n + 2 then data[#data] = nil end
--~ print('----------------------------------------------------------------------')
--~ print('value', value, 'f', scale.factor, 's', scale.domain, 'curr_s', scale.previous_domain)
--~ for i, v in pairs(timers) do
--~ print('timers', 'i', i, 's', v.domain, 't', v.remaining, 'f', v.factor)
--~ end
--~ print('length', #timers)
end
c.draw = LabelPlot.draw
c.update = update
return c

36
widget/poly/Bar.lua Normal file
View File

@ -0,0 +1,36 @@
local c = {}
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local set = function(obj, percent)
obj.percent = percent
obj.bar_path = obj._make_bar_path(percent)
if obj.critical.enabled(percent) then
obj.current_source = obj.critical.source
else
obj.current_source = obj.indicator_source
end
end
local draw = function(obj, cr)
_CAIRO_SET_LINE_WIDTH(cr, obj.thickness)
_CAIRO_SET_LINE_CAP(cr, obj.cap)
_CAIRO_APPEND_PATH(cr, obj.path)
_CAIRO_SET_SOURCE(cr, obj.source)
_CAIRO_STROKE(cr)
_CAIRO_APPEND_PATH(cr, obj.bar_path)
_CAIRO_SET_SOURCE(cr, obj.current_source)
_CAIRO_STROKE(cr)
end
c.set = set
c.draw = draw
return c

View File

@ -0,0 +1,34 @@
local c = {}
local Bar = require 'Bar'
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local _CAIRO_APPEND_PATH = cairo_append_path
local set = function(obj, index, percent)
Bar.set(obj.bars[index], percent)
end
local draw = function(obj, cr)
local first_bar = obj.bars[1]
_CAIRO_SET_LINE_WIDTH(cr, first_bar.thickness)
_CAIRO_SET_LINE_CAP(cr, first_bar.cap)
for i = 1, obj.bars.n do
local bar = obj.bars[i]
_CAIRO_SET_SOURCE(cr, bar.source)
_CAIRO_APPEND_PATH(cr, bar.path)
_CAIRO_STROKE(cr)
_CAIRO_SET_SOURCE(cr, bar.current_source)
_CAIRO_APPEND_PATH(cr, bar.bar_path)
_CAIRO_STROKE(cr)
end
end
c.set = set
c.draw = draw
return c

19
widget/poly/Line.lua Normal file
View File

@ -0,0 +1,19 @@
local c = {}
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local draw = function(obj, cr)
_CAIRO_APPEND_PATH(cr, obj.path)
_CAIRO_SET_LINE_WIDTH(cr, obj.thickness)
_CAIRO_SET_LINE_CAP(cr, obj.cap)
_CAIRO_SET_SOURCE(cr, obj.source)
_CAIRO_STROKE(cr)
end
c.draw = draw
return c

39
widget/poly/Poly.lua Normal file
View File

@ -0,0 +1,39 @@
local c = {}
local _CR = require 'CR'
local _CAIRO_NEW_PATH = cairo_new_path
local _CAIRO_MOVE_TO = cairo_move_to
local _CAIRO_LINE_TO = cairo_line_to
local _CAIRO_CLOSE_PATH = cairo_close_path
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_COPY_PATH = cairo_copy_path
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_SET_LINE_JOIN = cairo_set_line_join
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local create_path = function(closed, ...)
_CAIRO_NEW_PATH(_CR)
_CAIRO_MOVE_TO(_CR, arg[1].x, arg[1].y)
for i = 2, #arg do
_CAIRO_LINE_TO(_CR, arg[i].x, arg[i].y)
end
if closed then _CAIRO_CLOSE_PATH(_CR) end
return _CAIRO_COPY_PATH(_CR)
end
local draw = function(obj, cr)
_CAIRO_APPEND_PATH(cr, obj.path)
_CAIRO_SET_LINE_WIDTH(cr, obj.thickness)
_CAIRO_SET_LINE_JOIN(cr, obj.join)
_CAIRO_SET_LINE_CAP(cr, obj.cap)
_CAIRO_SET_SOURCE(cr, obj.source)
_CAIRO_STROKE(cr)
end
c.create_path = create_path
c.draw = draw
return c

24
widget/rect/FillRect.lua Normal file
View File

@ -0,0 +1,24 @@
local c = {}
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_JOIN = cairo_set_line_join
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_FILL_PRESERVE = cairo_fill_preserve
local _CAIRO_STROKE = cairo_stroke
local draw = function(obj, cr)
_CAIRO_APPEND_PATH(cr, obj.path)
_CAIRO_SET_LINE_WIDTH(cr, obj.thickness)
_CAIRO_SET_LINE_JOIN(cr, obj.join)
_CAIRO_SET_SOURCE(cr, obj.fill_source)
_CAIRO_FILL_PRESERVE(cr)
_CAIRO_SET_SOURCE(cr, obj.source)
_CAIRO_STROKE(cr)
end
c.draw = draw
return c

19
widget/rect/Rect.lua Normal file
View File

@ -0,0 +1,19 @@
local c = {}
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_JOIN = cairo_set_line_join
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_STROKE = cairo_stroke
local draw = function(obj, cr)
_CAIRO_APPEND_PATH(cr, obj.path)
_CAIRO_SET_LINE_WIDTH(cr, obj.thickness)
_CAIRO_SET_LINE_JOIN(cr, obj.join)
_CAIRO_SET_SOURCE(cr, obj.source)
_CAIRO_STROKE(cr)
end
c.draw = draw
return c

View File

@ -0,0 +1,29 @@
local c = {}
local Text = require 'Text'
local _TONUMBER = tonumber
local set = function(obj, cr, text, force)
if text and text ~= obj.pretext then
obj.value = _TONUMBER(text) or 0
if force == 0 then
obj.current_source = obj.critical.source
elseif force == 1 then
obj.current_source = obj.source
else
if obj.critical.enabled(obj.value) then
obj.current_source = obj.critical.source
else
obj.current_source = obj.source
end
end
Text.set(obj, cr, text)
end
end
c.draw = Text.draw
c.set = set
return c

73
widget/text/Table.lua Normal file
View File

@ -0,0 +1,73 @@
local c = {}
local TextColumn = require 'TextColumn'
local Rect = require 'Rect'
local _CAIRO_SET_LINE_WIDTH = cairo_set_line_width
local _CAIRO_SET_LINE_CAP = cairo_set_line_cap
local _CAIRO_APPEND_PATH = cairo_append_path
local _CAIRO_STROKE = cairo_stroke
local _CAIRO_SET_FONT_FACE = cairo_set_font_face
local _CAIRO_SET_FONT_SIZE = cairo_set_font_size
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_MOVE_TO = cairo_move_to
local _CAIRO_SHOW_TEXT = cairo_show_text
local set = function(obj, cr, col_num, row_num, text)
local column = obj.table.columns[col_num]
TextColumn.set(column, cr, row_num, text)
end
local draw = function(obj, cr)
--draw rectangle
Rect.draw(obj, cr)
--draw headers
local tbl = obj.table
local columns = tbl.columns
local first_header = columns[1].header
_CAIRO_SET_SOURCE(cr, first_header.source)
_CAIRO_SET_FONT_FACE(cr, first_header.font_face)
_CAIRO_SET_FONT_SIZE(cr, first_header.font_size)
for c = 1, tbl.num_columns do
local header = columns[c].header
_CAIRO_MOVE_TO(cr, header.x, header.y)
_CAIRO_SHOW_TEXT(cr, header.text)
end
--draw rows
local first_cell = columns[1].rows[1]
_CAIRO_SET_SOURCE(cr, first_cell.source)
_CAIRO_SET_FONT_FACE(cr, first_cell.font_face)
_CAIRO_SET_FONT_SIZE(cr, first_cell.font_size)
for c = 1, tbl.num_columns do
local rows = columns[c].rows
for r = 1, rows.n do
local row = rows[r]
_CAIRO_MOVE_TO(cr, row.x, row.y)
_CAIRO_SHOW_TEXT(cr, row.text)
end
end
--draw separators
local separators = tbl.separators
local first_separator = separators[1]
_CAIRO_SET_SOURCE(cr, first_separator.source)
_CAIRO_SET_LINE_WIDTH(cr, first_separator.thickness)
_CAIRO_SET_LINE_CAP(cr, first_separator.cap)
for i = 1, separators.n do
local line = separators[i]
_CAIRO_APPEND_PATH(cr, line.path)
_CAIRO_STROKE(cr)
end
end
c.set = set
c.draw = draw
return c

84
widget/text/Text.lua Normal file
View File

@ -0,0 +1,84 @@
local c = {}
local _STRING_SUB = string.sub
local _CAIRO_SET_FONT_FACE = cairo_set_font_face
local _CAIRO_SET_FONT_SIZE = cairo_set_font_size
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_MOVE_TO = cairo_move_to
local _CAIRO_SHOW_TEXT = cairo_show_text
local _CAIRO_TEXT_EXTENTS = cairo_text_extents
local te = cairo_text_extents_t:create()
tolua.takeownership(te)
local trim_to_length = function(text, len)
if #text > len then
return _STRING_SUB(text, 1, len)..'...'
else
return text
end
end
local draw = function(obj, cr)
_CAIRO_SET_FONT_FACE(cr, obj.font_face)
_CAIRO_SET_FONT_SIZE(cr, obj.font_size)
_CAIRO_SET_SOURCE(cr, obj.current_source)
_CAIRO_MOVE_TO(cr, obj.x, obj.y)
_CAIRO_SHOW_TEXT(cr, obj.text)
end
local set = function(obj, cr, text)
if text and text ~= obj.pretext then
obj.pretext = text
if obj.append_front then text = obj.append_front..text end
if obj.append_end then text = text..obj.append_end end
if text ~= obj.text then
local x_align = obj.x_align
local te = te
_CAIRO_SET_FONT_SIZE(cr, obj.font_size)
_CAIRO_SET_FONT_FACE(cr, obj.font_face)
_CAIRO_TEXT_EXTENTS(cr, text, te)
obj.width = te.width
if x_align == 'left' then obj.delta_x = -te.x_bearing
elseif x_align == 'center' then obj.delta_x = -(te.x_bearing + obj.width * 0.5)
elseif x_align == 'right' then obj.delta_x = -(te.x_bearing + obj.width)
end
obj.x = obj.x_ref + obj.delta_x
end
obj.text = text
end
end
local move_to_x = function(obj, x)
if x ~= obj.x then
obj.x_ref = x
obj.x = x + obj.delta_x
end
end
local move_to_y = function(obj, y)
if y ~= obj.y then
obj.y_ref = y
obj.y = y + obj.delta_y
end
end
local move_to = function(obj, x, y)
move_to_X(obj, x)
move_to_Y(obj, y)
end
c.trim_to_length = trim_to_length
c.set = set
c.draw = draw
c.move_to = move_to
c.move_to_x = move_to_x
c.move_to_y = move_to_y
return c

View File

@ -0,0 +1,38 @@
local c = {}
local Text = require 'Text'
local _CAIRO_SET_FONT_FACE = cairo_set_font_face
local _CAIRO_SET_FONT_SIZE = cairo_set_font_size
local _CAIRO_SET_SOURCE = cairo_set_source
local _CAIRO_MOVE_TO = cairo_move_to
local _CAIRO_SHOW_TEXT = cairo_show_text
local _STRING_SUB = string.sub
local set = function(obj, cr, row_num, text)
if obj.max_length then
Text.set(obj.rows[row_num], cr, Text.trim_to_length(text, obj.max_length))
else
Text.set(obj.rows[row_num], cr, text)
end
end
local draw = function(obj, cr)
local rep_row = obj.rows[1]
_CAIRO_SET_FONT_FACE(cr, rep_row.font_face)
_CAIRO_SET_FONT_SIZE(cr, rep_row.font_size)
_CAIRO_SET_SOURCE(cr, rep_row.source)
local rows = obj.rows
for i = 1, rows.n do
local row = rows[i]
_CAIRO_MOVE_TO(cr, row.x, row.y)
_CAIRO_SHOW_TEXT(cr, row.text)
end
end
c.set = set
c.draw = draw
return c