ENH put rest of configurable options in yaml file

This commit is contained in:
Nathan Dwarshuis 2022-07-19 00:54:46 -04:00
parent efa4319acd
commit bdca0c6511
7 changed files with 436 additions and 356 deletions

View File

@ -58,6 +58,18 @@ theme:
plot_label: 8 plot_label: 8
table: 11 table: 11
header: 15 header: 15
geometry:
plot:
seconds: 90
ticks: [9, 4]
table:
name_chars: 8
padding: [6, 15]
header_padding: 20
row_spacing: 13
header:
underline_offset: 26
padding: 19
patterns: patterns:
header: 0xefefef header: 0xefefef
panel: panel:

View File

@ -1,7 +1,6 @@
local geom = require 'geom' local geom = require 'geom'
local format = require 'format' local format = require 'format'
local color = require 'color' local color = require 'color'
-- local theme = require 'theme'
local dial = require 'dial' local dial = require 'dial'
local rect = require 'rect' local rect = require 'rect'
local fill_rect = require 'fill_rect' local fill_rect = require 'fill_rect'
@ -22,6 +21,7 @@ local pure = require 'pure'
local compile_patterns local compile_patterns
-- TODO move to color module
compile_patterns = function(patterns) compile_patterns = function(patterns)
local r = {} local r = {}
for k, v in pairs(patterns) do for k, v in pairs(patterns) do
@ -59,27 +59,24 @@ return function(config)
local font = config.theme.font local font = config.theme.font
local font_sizes = font.sizes local font_sizes = font.sizes
local font_family = font.family local font_family = font.family
local geometry = config.theme.geometry
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- constants -- constants
local HEADER_HEIGHT = 45 local CAP_ROUND = CAIRO_LINE_CAP_ROUND
local HEADER_UNDERLINE_CAP = CAIRO_LINE_CAP_ROUND local CAP_BUTT = CAIRO_LINE_CAP_BUTT
local HEADER_UNDERLINE_OFFSET = 26 local JOIN_MITER = CAIRO_LINE_JOIN_MITER
local FONT_BOLD = CAIRO_FONT_WEIGHT_BOLD
local FONT_NORMAL = CAIRO_FONT_WEIGHT_NORMAL
local HEADER_UNDERLINE_CAP = CAP_ROUND
local HEADER_UNDERLINE_THICKNESS = 3 local HEADER_UNDERLINE_THICKNESS = 3
local SEPARATOR_THICKNESS = 1 local SEPARATOR_THICKNESS = 1
local TABLE_BODY_FORMAT = 8
local TABLE_VERT_PAD = 15
local TABLE_HORZ_PAD = 5
local TABLE_HEADER_PAD = 20
local TABLE_LINE_THICKNESS = 1 local TABLE_LINE_THICKNESS = 1
local PLOT_NUM_POINTS = 90
local PLOT_GRID_X_N = 9
local PLOT_GRID_Y_N = 4
local ARC_WIDTH = 2 local ARC_WIDTH = 2
local DIAL_THETA0 = 90 local DIAL_THETA0 = 90
@ -89,199 +86,199 @@ return function(config)
-- line helper functions -- line helper functions
local _make_horizontal_line = function(x, y, w) local _make_horizontal_line = function(x, y, w)
return geom.make_line(geom.make_point(x, y), geom.make_point(x + w, y)) return geom.make_line(geom.make_point(x, y), geom.make_point(x + w, y))
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- text helper functions -- text helper functions
local make_font_spec = function(f, size, bold) local make_font_spec = function(f, size, bold)
return { return {
family = f, family = f,
size = size, size = size,
weight = bold and CAIRO_font_family_WEIGHT_BOLD or CAIRO_font_family_WEIGHT_NORMAL, weight = bold and FONT_BOLD or FONT_NORMAL,
slant = CAIRO_font_family_WEIGHT_NORMAL, slant = FONT_NORMAL,
} }
end end
local normal_font_spec = make_font_spec(font_family, font_sizes.normal, false) local normal_font_spec = make_font_spec(font_family, font_sizes.normal, false)
local label_font_spec = make_font_spec(font_family, font_sizes.plot_label, false) local label_font_spec = make_font_spec(font_family, font_sizes.plot_label, false)
local _text_row_style = function(x_align, color) local _text_row_style = function(x_align, _color)
return text.config(normal_font_spec, color, x_align, 'center') return text.config(normal_font_spec, _color, x_align, 'center')
end end
local _left_text_style = _text_row_style('left', patterns.text.inactive) local _left_text_style = _text_row_style('left', patterns.text.inactive)
local _right_text_style = _text_row_style('right', patterns.text.active) local _right_text_style = _text_row_style('right', patterns.text.active)
local _bare_text = function(pt, _text, _style) local _bare_text = function(pt, _text, _style)
return text.make_plain(pt, _text, _style) return text.make_plain(pt, _text, _style)
end end
local _left_text = function(pt, _text) local _left_text = function(pt, _text)
return _bare_text(pt, _text, _left_text_style) return _bare_text(pt, _text, _left_text_style)
end end
local _right_text = function(pt, _text) local _right_text = function(pt, _text)
return _bare_text(pt, _text, _right_text_style) return _bare_text(pt, _text, _right_text_style)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- timeseries helper functions -- timeseries helper functions
local _default_grid_config = timeseries.grid_config( local _default_grid_config = timeseries.grid_config(
PLOT_GRID_X_N, geometry.plot.ticks[1],
PLOT_GRID_Y_N, geometry.plot.ticks[2],
patterns.plot.grid patterns.plot.grid
) )
local _default_plot_config = timeseries.config( local _default_plot_config = timeseries.config(
PLOT_NUM_POINTS, geometry.plot.seconds,
patterns.plot.outline, patterns.plot.outline,
patterns.plot.data.border, patterns.plot.data.border,
patterns.plot.data.fill, patterns.plot.data.fill,
_default_grid_config _default_grid_config
) )
local _format_percent_label = function(_) local _format_percent_label = function(_)
return function(z) return string.format('%i%%', z * 100) end return function(z) return string.format('%i%%', math.floor(z * 100)) end
end end
local _format_percent_maybe = function(z) local _format_percent_maybe = function(z)
if z == -1 then return 'N/A' else return string.format('%s%%', z) end if z == -1 then return 'N/A' else return string.format('%s%%', z) end
end end
local _percent_label_config = timeseries.label_config( local _percent_label_config = timeseries.label_config(
patterns.text.inactive, patterns.text.inactive,
label_font_spec, label_font_spec,
_format_percent_label _format_percent_label
) )
local _make_timeseries = function(x, y, w, h, label_config, update_freq) local _make_timeseries = function(x, y, w, h, label_config, update_freq)
return timeseries.make( return timeseries.make(
geom.make_box(x, y, w, h), geom.make_box(x, y, w, h),
update_freq, update_freq,
_default_plot_config, _default_plot_config,
label_config label_config
) )
end end
local _make_tagged_percent_timeseries = function(x, y, w, h, spacing, label, update_freq, _format) local _make_tagged_percent_timeseries = function(x, y, w, h, spacing, label, update_freq, _format)
return { return {
label = _left_text(geom.make_point(x, y), label), label = _left_text(geom.make_point(x, y), label),
value = text_threshold.make_formatted( value = text_threshold.make_formatted(
geom.make_point(x + w, y), geom.make_point(x + w, y),
nil, nil,
_right_text_style, _right_text_style,
_format, _format,
text_threshold.config(patterns.text.critical, 80, false) text_threshold.config(patterns.text.critical, 80, false)
), ),
plot = M.make_percent_timeseries( plot = M.make_percent_timeseries(
x, x,
y + spacing, y + spacing,
w, w,
h, h,
update_freq update_freq
), ),
} }
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- scaled timeseries helper functions -- scaled timeseries helper functions
local _base_2_scale_data = function(m) local _base_2_scale_data = function(m)
return scaled_timeseries.scaling_parameters(2, m, 0.9) return scaled_timeseries.scaling_parameters(2, m, 0.9)
end end
local _make_scaled_timeseries = function(x, y, w, h, f, min_domain, update_freq) local _make_scaled_timeseries = function(x, y, w, h, f, min_domain, update_freq)
return scaled_timeseries.make( return scaled_timeseries.make(
geom.make_box(x, y, w, h), geom.make_box(x, y, w, h),
update_freq, update_freq,
_default_plot_config, _default_plot_config,
timeseries.label_config(patterns.text.inactive, label_font_spec, f), timeseries.label_config(patterns.text.inactive, label_font_spec, f),
_base_2_scale_data(min_domain) _base_2_scale_data(min_domain)
) )
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- header -- header
M.make_header = function(x, y, w, _text) M.make_header = function(x, y, w, _text)
local bottom_y = y + HEADER_HEIGHT local underline_y = y + geometry.header.underline_offset
local underline_y = y + HEADER_UNDERLINE_OFFSET local bottom_y = underline_y + geometry.header.padding
return { return {
text = text.make_plain( text = text.make_plain(
geom.make_point(x, y), geom.make_point(x, y),
_text, _text,
text.config( text.config(
make_font_spec(font_family, font_sizes.header, true), make_font_spec(font_family, font_sizes.header, true),
patterns.header, patterns.header,
'left', 'left',
'top' 'top'
) )
), ),
bottom_y = bottom_y, bottom_y = bottom_y,
underline = line.make( underline = line.make(
_make_horizontal_line(x, underline_y, w), _make_horizontal_line(x, underline_y, w),
line.config( line.config(
style.line(HEADER_UNDERLINE_THICKNESS, HEADER_UNDERLINE_CAP), style.line(HEADER_UNDERLINE_THICKNESS, HEADER_UNDERLINE_CAP),
patterns.header, patterns.header,
true true
) )
) )
} }
end end
M.draw_header = function(cr, header) M.draw_header = function(cr, header)
text.draw(header.text, cr) text.draw(header.text, cr)
line.draw(header.underline, cr) line.draw(header.underline, cr)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- percent timeseries -- percent timeseries
M.make_percent_timeseries = function(x, y, w, h, update_freq) M.make_percent_timeseries = function(x, y, w, h, update_freq)
return _make_timeseries(x, y, w, h, _percent_label_config, update_freq) return _make_timeseries(x, y, w, h, _percent_label_config, update_freq)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- tagged percent timeseries -- tagged percent timeseries
M.make_tagged_percent_timeseries = function(x, y, w, h, spacing, label, update_freq) M.make_tagged_percent_timeseries = function(x, y, w, h, spacing, label, update_freq)
return _make_tagged_percent_timeseries( return _make_tagged_percent_timeseries(
x, y, w, h, spacing, label, update_freq, '%s%%' x, y, w, h, spacing, label, update_freq, '%s%%'
) )
end end
M.make_tagged_maybe_percent_timeseries = function(x, y, w, h, spacing, label, update_freq) M.make_tagged_maybe_percent_timeseries = function(x, y, w, h, spacing, label, update_freq)
return _make_tagged_percent_timeseries( return _make_tagged_percent_timeseries(
x, y, w, h, spacing, label, update_freq, _format_percent_maybe x, y, w, h, spacing, label, update_freq, _format_percent_maybe
) )
end end
M.tagged_percent_timeseries_draw_static = function(pp, cr) M.tagged_percent_timeseries_draw_static = function(pp, cr)
text.draw(pp.label, cr) text.draw(pp.label, cr)
timeseries.draw_static(pp.plot, cr) timeseries.draw_static(pp.plot, cr)
end end
M.tagged_percent_timeseries_draw_dynamic = function(obj, cr) M.tagged_percent_timeseries_draw_dynamic = function(obj, cr)
text_threshold.draw(obj.value, cr) text_threshold.draw(obj.value, cr)
timeseries.draw_dynamic(obj.plot, cr) timeseries.draw_dynamic(obj.plot, cr)
end end
M.tagged_percent_timeseries_set = function(obj, percent) M.tagged_percent_timeseries_set = function(obj, percent)
local _percent = pure.round_percent(percent) local _percent = pure.round_percent(percent)
text.set(obj.value, _percent) text.set(obj.value, _percent)
timeseries.update(obj.plot, _percent / 100) timeseries.update(obj.plot, _percent / 100)
end end
M.tagged_maybe_percent_timeseries_set = function(obj, percent) M.tagged_maybe_percent_timeseries_set = function(obj, percent)
if percent == false then if percent == false then
text.set(obj.value, -1) text.set(obj.value, -1)
timeseries.update(obj.plot, 0) timeseries.update(obj.plot, 0)
else else
M.tagged_percent_timeseries_set(obj, percent) M.tagged_percent_timeseries_set(obj, percent)
end end
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
@ -293,401 +290,419 @@ return function(config)
-- Note that this for now only works when the number of y grid lines if 4, as -- Note that this for now only works when the number of y grid lines if 4, as
-- it gives enough resolution for 1, 0.75, 0.5, and 0.25 but no more -- it gives enough resolution for 1, 0.75, 0.5, and 0.25 but no more
M.y_label_format_string = function(plot_max, unit) M.y_label_format_string = function(plot_max, unit)
local num_fmt local num_fmt
if plot_max < 2 then if plot_max < 2 then
num_fmt = '%.2f' num_fmt = '%.2f'
elseif plot_max < 4 then elseif plot_max < 4 then
num_fmt = '%.1f' num_fmt = '%.1f'
else else
num_fmt = '%.0f' num_fmt = '%.0f'
end end
return string.format('%s %s', num_fmt, unit) return string.format('%s %s', num_fmt, unit)
end end
M.converted_y_label_format_generator = function(unit) M.converted_y_label_format_generator = function(unit)
return function(plot_max) return function(plot_max)
local new_prefix, new_max = format.convert_data_val(plot_max) local new_prefix, new_max = format.convert_data_val(plot_max)
local conversion_factor = plot_max / new_max local conversion_factor = plot_max / new_max
local fmt = M.y_label_format_string(new_max, new_prefix..unit..'/s') local fmt = M.y_label_format_string(new_max, new_prefix..unit..'/s')
return function(bytes) return function(bytes)
return string.format(fmt, bytes / conversion_factor) return string.format(fmt, bytes / conversion_factor)
end end
end end
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- tagged scaled plot -- tagged scaled plot
M.make_tagged_scaled_timeseries = function(x, y, w, h, format_fun, label_fun, M.make_tagged_scaled_timeseries = function(x, y, w, h, format_fun, label_fun,
spacing, label, min_domain, spacing, label, min_domain,
update_freq) update_freq)
return { return {
label = _left_text(geom.make_point(x, y), label), label = _left_text(geom.make_point(x, y), label),
value = text.make_formatted( value = text.make_formatted(
geom.make_point(x + w, y), geom.make_point(x + w, y),
0, 0,
_right_text_style, _right_text_style,
format_fun format_fun
), ),
plot = _make_scaled_timeseries(x, y + spacing, w, h, label_fun, min_domain, update_freq), plot = _make_scaled_timeseries(
} x,
y + spacing,
w,
h,
label_fun,
min_domain,
update_freq
),
}
end end
M.tagged_scaled_timeseries_draw_static = function(asp, cr) M.tagged_scaled_timeseries_draw_static = function(asp, cr)
text.draw(asp.label, cr) text.draw(asp.label, cr)
end end
M.tagged_scaled_timeseries_draw_dynamic = function(asp, cr) M.tagged_scaled_timeseries_draw_dynamic = function(asp, cr)
text.draw(asp.value, cr) text.draw(asp.value, cr)
scaled_timeseries.draw_dynamic(asp.plot, cr) scaled_timeseries.draw_dynamic(asp.plot, cr)
end end
M.tagged_scaled_timeseries_set = function(asp, value) M.tagged_scaled_timeseries_set = function(asp, value)
text.set(asp.value, value) text.set(asp.value, value)
scaled_timeseries.update(asp.plot, value) scaled_timeseries.update(asp.plot, value)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- rate timecourse plots -- rate timecourse plots
local make_differential = function(update_frequency) local make_differential = function(update_frequency)
return function(x0, x1) return function(x0, x1)
-- mask overflow -- mask overflow
if x1 > x0 then if x1 > x0 then
return (x1 - x0) * update_frequency return (x1 - x0) * update_frequency
else else
return 0 return 0
end end
end end
end end
M.make_rate_timeseries = function(x, y, w, h, format_fun, label_fun, spacing, M.make_rate_timeseries = function(x, y, w, h, format_fun, label_fun, spacing,
label, min_domain, update_freq, init) label, min_domain, update_freq, init)
return { return {
label = _left_text(geom.make_point(x, y), label), label = _left_text(geom.make_point(x, y), label),
value = text.make_formatted( value = text.make_formatted(
geom.make_point(x + w, y), geom.make_point(x + w, y),
0, 0,
_right_text_style, _right_text_style,
format_fun format_fun
), ),
plot = _make_scaled_timeseries(x, y + spacing, w, h, label_fun, min_domain, update_freq), plot = _make_scaled_timeseries(
prev_value = init, x,
derive = make_differential(update_freq), y + spacing,
} w,
h,
label_fun,
min_domain,
update_freq
),
prev_value = init,
derive = make_differential(update_freq),
}
end end
M.update_rate_timeseries = function(obj, value) M.update_rate_timeseries = function(obj, value)
local rate = obj.derive(obj.prev_value, value) local rate = obj.derive(obj.prev_value, value)
text.set(obj.value, rate) text.set(obj.value, rate)
scaled_timeseries.update(obj.plot, rate) scaled_timeseries.update(obj.plot, rate)
obj.prev_value = value obj.prev_value = value
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- circle -- circle
M.make_circle = function(x, y, r) M.make_circle = function(x, y, r)
return circle.make( return circle.make(
geom.make_circle(x, y, r), geom.make_circle(x, y, r),
circle.config(style.line(ARC_WIDTH, CAIRO_LINE_CAP_BUTT), patterns.border) circle.config(style.line(ARC_WIDTH, CAP_BUTT), patterns.border)
) )
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- ring with text data in the center -- ring with text data in the center
M.make_text_circle = function(x, y, r, fmt, threshhold, pre_function) M.make_text_circle = function(x, y, r, fmt, threshhold, pre_function)
return { return {
ring = M.make_circle(x, y, r), ring = M.make_circle(x, y, r),
value = text_threshold.make_formatted( value = text_threshold.make_formatted(
geom.make_point(x, y), geom.make_point(x, y),
0, 0,
text.config(normal_font_spec, patterns.text.active, 'center', 'center'), text.config(normal_font_spec, patterns.text.active, 'center', 'center'),
fmt, fmt,
text_threshold.config(patterns.text.critical, threshhold, pre_function) text_threshold.config(patterns.text.critical, threshhold, pre_function)
), ),
} }
end end
M.text_circle_draw_static = function(tr, cr) M.text_circle_draw_static = function(tr, cr)
arc.draw(tr.ring, cr) arc.draw(tr.ring, cr)
end end
M.text_circle_draw_dynamic = function(tr, cr) M.text_circle_draw_dynamic = function(tr, cr)
text_threshold.draw(tr.value, cr) text_threshold.draw(tr.value, cr)
end end
M.text_circle_set = function(tr, value) M.text_circle_set = function(tr, value)
text_threshold.set(tr.value, value) text_threshold.set(tr.value, value)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- dial -- dial
local threshold_indicator = function(threshold) local threshold_indicator = function(threshold)
return source.threshold_config( return source.threshold_config(
patterns.indicator.fg.active, patterns.indicator.fg.active,
patterns.indicator.fg.critical, patterns.indicator.fg.critical,
threshold threshold
) )
end end
M.make_dial = function(x, y, radius, thickness, threshold, _format, pre_function) M.make_dial = function(x, y, radius, thickness, threshold, _format, pre_function)
return { return {
dial = dial.make( dial = dial.make(
geom.make_arc(x, y, radius, DIAL_THETA0, DIAL_THETA1), geom.make_arc(x, y, radius, DIAL_THETA0, DIAL_THETA1),
arc.config(style.line(thickness, CAIRO_LINE_CAP_BUTT), patterns.indicator.bg), arc.config(style.line(thickness, CAP_BUTT), patterns.indicator.bg),
threshold_indicator(threshold) threshold_indicator(threshold)
), ),
text_circle = M.make_text_circle(x, y, radius - thickness / 2 - 2, _format, threshold, pre_function), text_circle = M.make_text_circle(x, y, radius - thickness / 2 - 2, _format, threshold, pre_function),
} }
end end
M.dial_set = function(dl, value) M.dial_set = function(dl, value)
dial.set(dl.dial, value) dial.set(dl.dial, value)
M.text_circle_set(dl.text_circle, value) M.text_circle_set(dl.text_circle, value)
end end
M.dial_draw_static = function(dl, cr) M.dial_draw_static = function(dl, cr)
dial.draw_static(dl.dial, cr) dial.draw_static(dl.dial, cr)
M.text_circle_draw_static(dl.text_circle, cr) M.text_circle_draw_static(dl.text_circle, cr)
end end
M.dial_draw_dynamic = function(dl, cr) M.dial_draw_dynamic = function(dl, cr)
dial.draw_dynamic(dl.dial, cr) dial.draw_dynamic(dl.dial, cr)
M.text_circle_draw_dynamic(dl.text_circle, cr) M.text_circle_draw_dynamic(dl.text_circle, cr)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- compound dial -- compound dial
M.make_compound_dial = function(x, y, outer_radius, inner_radius, thickness, M.make_compound_dial = function(x, y, outer_radius, inner_radius, thickness,
threshold, num_dials) threshold, num_dials)
return compound_dial.make( return compound_dial.make(
geom.make_arc(x, y, outer_radius, DIAL_THETA0, DIAL_THETA1), geom.make_arc(x, y, outer_radius, DIAL_THETA0, DIAL_THETA1),
arc.config(style.line(thickness, CAIRO_LINE_CAP_BUTT), patterns.indicator.bg), arc.config(style.line(thickness, CAP_BUTT), patterns.indicator.bg),
threshold_indicator(threshold), threshold_indicator(threshold),
inner_radius, inner_radius,
num_dials num_dials
) )
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- annotated compound bar -- annotated compound bar
M.make_compound_bar = function(x, y, w, pad, labels, spacing, thickness, threshold) M.make_compound_bar = function(x, y, w, pad, labels, spacing, thickness, threshold)
return { return {
labels = text_column.make( labels = text_column.make(
geom.make_point(x, y), geom.make_point(x, y),
labels, labels,
_left_text_style, _left_text_style,
nil, nil,
spacing spacing
), ),
bars = compound_bar.make( bars = compound_bar.make(
geom.make_point(x + pad, y), geom.make_point(x + pad, y),
w - pad, w - pad,
line.config( line.config(
style.line(thickness, CAIRO_LINE_CAP_BUTT), style.line(thickness, CAP_BUTT),
patterns.indicator.bg, patterns.indicator.bg,
true true
), ),
threshold_indicator(threshold), threshold_indicator(threshold),
spacing, spacing,
#labels, #labels,
false false
) )
} }
end end
M.compound_bar_draw_static = function(cb, cr) M.compound_bar_draw_static = function(cb, cr)
text_column.draw(cb.labels, cr) text_column.draw(cb.labels, cr)
compound_bar.draw_static(cb.bars, cr) compound_bar.draw_static(cb.bars, cr)
end end
M.compound_bar_draw_dynamic = function(cb, cr) M.compound_bar_draw_dynamic = function(cb, cr)
compound_bar.draw_dynamic(cb.bars, cr) compound_bar.draw_dynamic(cb.bars, cr)
end end
M.compound_bar_set = function(cb, i, value) M.compound_bar_set = function(cb, i, value)
compound_bar.set(cb.bars, i, value) compound_bar.set(cb.bars, i, value)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- separator (eg a horizontal line) -- separator (eg a horizontal line)
M.make_separator = function(x, y, w) M.make_separator = function(x, y, w)
return line.make( return line.make(
_make_horizontal_line(x, y, w), _make_horizontal_line(x, y, w),
line.config( line.config(
style.line(SEPARATOR_THICKNESS, CAIRO_LINE_CAP_BUTT), style.line(SEPARATOR_THICKNESS, CAP_BUTT),
patterns.border, patterns.border,
true true
) )
) )
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- text row (label with a value, aligned as far apart as possible) -- text row (label with a value, aligned as far apart as possible)
M.make_text_row = function(x, y, w, label) M.make_text_row = function(x, y, w, label)
return { return {
label = _left_text(geom.make_point(x, y), label), label = _left_text(geom.make_point(x, y), label),
value = _right_text(geom.make_point(x + w, y), nil), value = _right_text(geom.make_point(x + w, y), nil),
} }
end end
M.text_row_draw_static = function(row, cr) M.text_row_draw_static = function(row, cr)
text.draw(row.label, cr) text.draw(row.label, cr)
end end
M.text_row_draw_dynamic = function(row, cr) M.text_row_draw_dynamic = function(row, cr)
text.draw(row.value, cr) text.draw(row.value, cr)
end end
M.text_row_set = function(row, value) M.text_row_set = function(row, value)
text.set(row.value, value) text.set(row.value, value)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- text row with critical indicator -- text row with critical indicator
M.make_threshold_text_row = function(x, y, w, label, append_end, limit) M.make_threshold_text_row = function(x, y, w, label, append_end, limit)
return{ return{
label = _left_text(geom.make_point(x, y), label), label = _left_text(geom.make_point(x, y), label),
value = text_threshold.make_formatted( value = text_threshold.make_formatted(
geom.make_point(x + w, y), geom.make_point(x + w, y),
nil, nil,
_right_text_style, _right_text_style,
append_end, append_end,
text_threshold.config(patterns.text.critical, limit, false) text_threshold.config(patterns.text.critical, limit, false)
) )
} }
end end
M.threshold_text_row_draw_static = M.text_row_draw_static M.threshold_text_row_draw_static = M.text_row_draw_static
M.threshold_text_row_draw_dynamic = function(row, cr) M.threshold_text_row_draw_dynamic = function(row, cr)
text_threshold.draw(row.value, cr) text_threshold.draw(row.value, cr)
end end
M.threshold_text_row_set = function(row, value) M.threshold_text_row_set = function(row, value)
text_threshold.set(row.value, value) text_threshold.set(row.value, value)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- multiple text row separated by spacing -- multiple text row separated by spacing
M.make_text_rows_formatted = function(x, y, w, spacing, labels, format) M.make_text_rows_formatted = function(x, y, w, spacing, labels, _format)
return { return {
labels = text_column.make( labels = text_column.make(
geom.make_point(x, y), geom.make_point(x, y),
labels, labels,
_left_text_style, _left_text_style,
nil, nil,
spacing spacing
), ),
values = text_column.make_n( values = text_column.make_n(
geom.make_point(x + w, y), geom.make_point(x + w, y),
#labels, #labels,
_right_text_style, _right_text_style,
format, _format,
spacing, spacing,
0 0
) )
} }
end end
M.make_text_rows = function(x, y, w, spacing, labels) M.make_text_rows = function(x, y, w, spacing, labels)
return M.make_text_rows_formatted( return M.make_text_rows_formatted(
x, x,
y, y,
w, w,
spacing, spacing,
labels, labels,
nil nil
) )
end end
M.text_rows_draw_static = function(rows, cr) M.text_rows_draw_static = function(rows, cr)
text_column.draw(rows.labels, cr) text_column.draw(rows.labels, cr)
end end
M.text_rows_draw_dynamic = function(rows, cr) M.text_rows_draw_dynamic = function(rows, cr)
text_column.draw(rows.values, cr) text_column.draw(rows.values, cr)
end end
M.text_rows_set = function(rows, i, value) M.text_rows_set = function(rows, i, value)
text_column.set(rows.values, i, value) text_column.set(rows.values, i, value)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- table -- table
local gtable = geometry.table
local padding = gtable.padding
local xpad = padding[1]
local ypad = padding[2]
local default_table_font_spec = make_font_spec(font_family, font_sizes.table, false) local default_table_font_spec = make_font_spec(font_family, font_sizes.table, false)
local col_fmt = gtable.name_chars > 0 and gtable.name_chars
local default_table_config = function(label) local default_table_config = function(label)
return tbl.config( return tbl.config(
rect.config( rect.config(
style.closed_poly(TABLE_LINE_THICKNESS, CAIRO_LINE_JOIN_MITER), style.closed_poly(TABLE_LINE_THICKNESS, JOIN_MITER),
patterns.border patterns.border
), ),
line.config( line.config(
style.line(TABLE_LINE_THICKNESS, CAIRO_LINE_CAP_BUTT), style.line(TABLE_LINE_THICKNESS, CAP_BUTT),
patterns.border, patterns.border,
true true
), ),
tbl.header_config( tbl.header_config(
default_table_font_spec, default_table_font_spec,
patterns.text.active, patterns.text.active,
TABLE_HEADER_PAD gtable.header_padding
), ),
tbl.body_config( tbl.body_config(
default_table_font_spec, default_table_font_spec,
patterns.text.inactive, patterns.text.inactive,
{ {
tbl.column_config('Name', TABLE_BODY_FORMAT), tbl.column_config('Name', col_fmt),
tbl.column_config('PID', false), tbl.column_config('PID', false),
tbl.column_config(label, false), tbl.column_config(label, false),
} }
), ),
tbl.padding( tbl.padding(xpad, ypad, xpad, ypad)
TABLE_HORZ_PAD, )
TABLE_VERT_PAD,
TABLE_HORZ_PAD,
TABLE_VERT_PAD
)
)
end
M.make_text_table = function(x, y, w, h, n, label)
return tbl.make(
geom.make_box(x, y, w, h),
n,
default_table_config(label)
)
end end
M.table_height = function(n) M.table_height = function(n)
return TABLE_VERT_PAD * 2 + TABLE_HEADER_PAD + 13 * n return ypad * 2 + gtable.header_padding + gtable.row_spacing * n
end
M.make_text_table = function(x, y, w, n, label)
local h = M.table_height(n)
return tbl.make(
geom.make_box(x, y, w, h),
n,
default_table_config(label)
)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- panel -- panel
M.make_panel = function(x, y, w, h, thickness) M.make_panel = function(x, y, w, h, thickness)
return fill_rect.make( return fill_rect.make(
geom.make_box(x, y, w, h), geom.make_box(x, y, w, h),
rect.config( rect.config(
style.closed_poly(thickness, CAIRO_LINE_JOIN_MITER), style.closed_poly(thickness, JOIN_MITER),
patterns.border patterns.border
), ),
patterns.panel.bg patterns.panel.bg
) )
end end
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- compile individual module -- compile individual module

View File

@ -179,7 +179,6 @@ return function(update_freq, config, common, width, point)
local mk_tbl = function(y) local mk_tbl = function(y)
local num_rows = config.table_rows local num_rows = config.table_rows
local table_height = common.table_height(num_rows)
local table_conky = pure.map_n( local table_conky = pure.map_n(
function(i) function(i)
return { return {
@ -193,7 +192,6 @@ return function(update_freq, config, common, width, point)
point.x, point.x,
y, y,
width, width,
table_height,
num_rows, num_rows,
'Mem (%)' 'Mem (%)'
) )
@ -206,7 +204,7 @@ return function(update_freq, config, common, width, point)
end end
return common.mk_acc( return common.mk_acc(
width, width,
table_height, common.table_height(num_rows),
update, update,
pure.partial(text_table.draw_static, obj), pure.partial(text_table.draw_static, obj),
pure.partial(text_table.draw_dynamic, obj) pure.partial(text_table.draw_dynamic, obj)

View File

@ -112,8 +112,7 @@ return function(update_freq, config, common, width, point)
set_state = nil, set_state = nil,
top = pure.concat( top = pure.concat(
pure.map(mk_rate_blockspec, config.rapl_specs), pure.map(mk_rate_blockspec, config.rapl_specs),
-- TODO what happens if this is nil? {{mk_bat, config.battery ~= '', 0}}
{{mk_bat, config.battery ~= nil, 0}}
) )
} }
end end

View File

@ -193,7 +193,6 @@ return function(update_freq, config, main_state, common, width, point)
local mk_tbl = function(y) local mk_tbl = function(y)
local num_rows = config.table_rows local num_rows = config.table_rows
local table_height = common.table_height(num_rows)
local table_conky = pure.map_n( local table_conky = pure.map_n(
function(i) return {pid = '${top pid '..i..'}', cpu = '${top cpu '..i..'}'} end, function(i) return {pid = '${top pid '..i..'}', cpu = '${top cpu '..i..'}'} end,
num_rows num_rows
@ -202,7 +201,6 @@ return function(update_freq, config, main_state, common, width, point)
point.x, point.x,
y, y,
width, width,
table_height,
num_rows, num_rows,
'CPU (%)' 'CPU (%)'
) )
@ -218,7 +216,7 @@ return function(update_freq, config, main_state, common, width, point)
end end
return common.mk_acc( return common.mk_acc(
width, width,
table_height, common.table_height(num_rows),
update, update,
pure.partial(text_table.draw_static, tbl), pure.partial(text_table.draw_static, tbl),
pure.partial(text_table.draw_dynamic, tbl) pure.partial(text_table.draw_dynamic, tbl)

View File

@ -14,6 +14,8 @@ return function(main_state, common, width, point)
TEXT_SPACING, TEXT_SPACING,
{'Kernel', 'Uptime', 'Last Upgrade', 'Last Sync'} {'Kernel', 'Uptime', 'Last Upgrade', 'Last Sync'}
) )
-- just update this once
common.text_rows_set(obj, 1, i_o.conky('$kernel'))
local update = function() local update = function()
local last_update, last_sync local last_update, last_sync
if main_state.pacman_stats then if main_state.pacman_stats then
@ -22,8 +24,6 @@ return function(main_state, common, width, point)
"^%d+%s+([^%s]+)%s+([^%s]+).*" "^%d+%s+([^%s]+)%s+([^%s]+).*"
) )
end end
-- TODO this doesn't need to be updated every time
common.text_rows_set(obj, 1, i_o.conky('$kernel'))
common.text_rows_set(obj, 2, i_o.conky('$uptime')) common.text_rows_set(obj, 2, i_o.conky('$uptime'))
common.text_rows_set(obj, 3, last_update) common.text_rows_set(obj, 3, last_update)
common.text_rows_set(obj, 4, last_sync) common.text_rows_set(obj, 4, last_sync)

View File

@ -71,10 +71,8 @@ properties:
additionalProperties: false additionalProperties: false
properties: properties:
battery: battery:
description: the battery device to use (if applicable) description: the battery device to use (or blank if none)
anyOf: type: string
- type: string
- type: "null"
rapl_specs: rapl_specs:
description: the Intel RAPL specs for which plots should be made description: the Intel RAPL specs for which plots should be made
type: array type: array
@ -181,7 +179,7 @@ properties:
network|pacman|filesystem|power|memory$" network|pacman|filesystem|power|memory$"
theme: theme:
required: [font, patterns] required: [font, geometry, patterns]
additionalProperties: false additionalProperties: false
properties: properties:
font: font:
@ -200,6 +198,66 @@ properties:
plot_label: *font_size plot_label: *font_size
table: *font_size table: *font_size
header: *font_size header: *font_size
geometry:
required: [plot, table]
additionalProperties: false
properties:
plot:
required: [seconds, ticks]
additionalProperties: false
properties:
seconds:
description: the number of seconds on each timeseries plot
type: integer
minimum: 30
ticks:
description: the number of ticks on the x/y axes
type: array
minItems: 2
maxItems: 2
items:
type: integer
minimum: 2
table:
required: [name_chars, padding, header_padding]
additionalProperties: false
properties:
name_chars:
description: |
the length to which the name column should be trimmed (if any)
type: integer
minimum: 0
padding:
description: the x/y padding around the table
type: array
minItems: 2
maxItems: 2
items:
type: integer
minimum: 0
header_padding:
description: the padding beneath the column headers
type: integer
minimum: 0
row_spacing:
description: the distance between the center of each row
type: integer
minimum: 10
header:
required: [underline_offset, padding]
additionalProperties: false
properties:
underline_offset:
description: the offset of the underline (from top of header)
type: integer
minimum: 10
padding:
description: the padding beneath the underline
type: integer
minimum: 0
patterns: patterns:
required: [header, panel, text, border, plot, indicator] required: [header, panel, text, border, plot, indicator]
additionalProperties: false additionalProperties: false
@ -215,10 +273,10 @@ properties:
properties: properties:
color: color:
type: integer type: integer
alpha: alpha: &alpha
anyOf: type: number
- type: "null" minimum: 0
- &alpha {type: number, minimum: 0, maximum: 1} maximum: 1
gradient: gradient:
type: array type: array
minItems: 2 minItems: 2