diff --git a/config.yml b/config.yml index 72493f2..d5b1f39 100644 --- a/config.yml +++ b/config.yml @@ -58,6 +58,18 @@ theme: plot_label: 8 table: 11 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: header: 0xefefef panel: diff --git a/drawing/common.lua b/drawing/common.lua index d4de6cc..42ef880 100644 --- a/drawing/common.lua +++ b/drawing/common.lua @@ -1,7 +1,6 @@ local geom = require 'geom' local format = require 'format' local color = require 'color' --- local theme = require 'theme' local dial = require 'dial' local rect = require 'rect' local fill_rect = require 'fill_rect' @@ -22,6 +21,7 @@ local pure = require 'pure' local compile_patterns +-- TODO move to color module compile_patterns = function(patterns) local r = {} for k, v in pairs(patterns) do @@ -59,27 +59,24 @@ return function(config) local font = config.theme.font local font_sizes = font.sizes local font_family = font.family + local geometry = config.theme.geometry ----------------------------------------------------------------------------- -- constants - local HEADER_HEIGHT = 45 - local HEADER_UNDERLINE_CAP = CAIRO_LINE_CAP_ROUND - local HEADER_UNDERLINE_OFFSET = 26 + local CAP_ROUND = CAIRO_LINE_CAP_ROUND + local CAP_BUTT = CAIRO_LINE_CAP_BUTT + 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 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 PLOT_NUM_POINTS = 90 - local PLOT_GRID_X_N = 9 - local PLOT_GRID_Y_N = 4 - local ARC_WIDTH = 2 local DIAL_THETA0 = 90 @@ -89,199 +86,199 @@ return function(config) -- line helper functions 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 ----------------------------------------------------------------------------- -- text helper functions local make_font_spec = function(f, size, bold) - return { - family = f, - size = size, - weight = bold and CAIRO_font_family_WEIGHT_BOLD or CAIRO_font_family_WEIGHT_NORMAL, - slant = CAIRO_font_family_WEIGHT_NORMAL, - } + return { + family = f, + size = size, + weight = bold and FONT_BOLD or FONT_NORMAL, + slant = FONT_NORMAL, + } end 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 _text_row_style = function(x_align, color) - return text.config(normal_font_spec, color, x_align, 'center') + local _text_row_style = function(x_align, _color) + return text.config(normal_font_spec, _color, x_align, 'center') end local _left_text_style = _text_row_style('left', patterns.text.inactive) local _right_text_style = _text_row_style('right', patterns.text.active) local _bare_text = function(pt, _text, _style) - return text.make_plain(pt, _text, _style) + return text.make_plain(pt, _text, _style) end local _left_text = function(pt, _text) - return _bare_text(pt, _text, _left_text_style) + return _bare_text(pt, _text, _left_text_style) end local _right_text = function(pt, _text) - return _bare_text(pt, _text, _right_text_style) + return _bare_text(pt, _text, _right_text_style) end ----------------------------------------------------------------------------- -- timeseries helper functions local _default_grid_config = timeseries.grid_config( - PLOT_GRID_X_N, - PLOT_GRID_Y_N, - patterns.plot.grid + geometry.plot.ticks[1], + geometry.plot.ticks[2], + patterns.plot.grid ) local _default_plot_config = timeseries.config( - PLOT_NUM_POINTS, - patterns.plot.outline, - patterns.plot.data.border, - patterns.plot.data.fill, - _default_grid_config + geometry.plot.seconds, + patterns.plot.outline, + patterns.plot.data.border, + patterns.plot.data.fill, + _default_grid_config ) 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 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 local _percent_label_config = timeseries.label_config( - patterns.text.inactive, - label_font_spec, - _format_percent_label + patterns.text.inactive, + label_font_spec, + _format_percent_label ) local _make_timeseries = function(x, y, w, h, label_config, update_freq) - return timeseries.make( - geom.make_box(x, y, w, h), - update_freq, - _default_plot_config, - label_config - ) + return timeseries.make( + geom.make_box(x, y, w, h), + update_freq, + _default_plot_config, + label_config + ) end local _make_tagged_percent_timeseries = function(x, y, w, h, spacing, label, update_freq, _format) - return { - label = _left_text(geom.make_point(x, y), label), - value = text_threshold.make_formatted( - geom.make_point(x + w, y), - nil, - _right_text_style, - _format, - text_threshold.config(patterns.text.critical, 80, false) - ), - plot = M.make_percent_timeseries( - x, - y + spacing, - w, - h, - update_freq - ), - } + return { + label = _left_text(geom.make_point(x, y), label), + value = text_threshold.make_formatted( + geom.make_point(x + w, y), + nil, + _right_text_style, + _format, + text_threshold.config(patterns.text.critical, 80, false) + ), + plot = M.make_percent_timeseries( + x, + y + spacing, + w, + h, + update_freq + ), + } end ----------------------------------------------------------------------------- -- scaled timeseries helper functions 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 local _make_scaled_timeseries = function(x, y, w, h, f, min_domain, update_freq) - return scaled_timeseries.make( - geom.make_box(x, y, w, h), - update_freq, - _default_plot_config, - timeseries.label_config(patterns.text.inactive, label_font_spec, f), - _base_2_scale_data(min_domain) - ) + return scaled_timeseries.make( + geom.make_box(x, y, w, h), + update_freq, + _default_plot_config, + timeseries.label_config(patterns.text.inactive, label_font_spec, f), + _base_2_scale_data(min_domain) + ) end ----------------------------------------------------------------------------- -- header M.make_header = function(x, y, w, _text) - local bottom_y = y + HEADER_HEIGHT - local underline_y = y + HEADER_UNDERLINE_OFFSET - return { - text = text.make_plain( - geom.make_point(x, y), - _text, - text.config( + local underline_y = y + geometry.header.underline_offset + local bottom_y = underline_y + geometry.header.padding + return { + text = text.make_plain( + geom.make_point(x, y), + _text, + text.config( make_font_spec(font_family, font_sizes.header, true), patterns.header, 'left', 'top' - ) - ), - bottom_y = bottom_y, - underline = line.make( - _make_horizontal_line(x, underline_y, w), - line.config( + ) + ), + bottom_y = bottom_y, + underline = line.make( + _make_horizontal_line(x, underline_y, w), + line.config( style.line(HEADER_UNDERLINE_THICKNESS, HEADER_UNDERLINE_CAP), patterns.header, true - ) - ) - } + ) + ) + } end M.draw_header = function(cr, header) - text.draw(header.text, cr) - line.draw(header.underline, cr) + text.draw(header.text, cr) + line.draw(header.underline, cr) end ----------------------------------------------------------------------------- -- percent timeseries 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 ----------------------------------------------------------------------------- -- tagged percent timeseries M.make_tagged_percent_timeseries = function(x, y, w, h, spacing, label, update_freq) - return _make_tagged_percent_timeseries( - x, y, w, h, spacing, label, update_freq, '%s%%' - ) + return _make_tagged_percent_timeseries( + x, y, w, h, spacing, label, update_freq, '%s%%' + ) end M.make_tagged_maybe_percent_timeseries = function(x, y, w, h, spacing, label, update_freq) - return _make_tagged_percent_timeseries( - x, y, w, h, spacing, label, update_freq, _format_percent_maybe - ) + return _make_tagged_percent_timeseries( + x, y, w, h, spacing, label, update_freq, _format_percent_maybe + ) end M.tagged_percent_timeseries_draw_static = function(pp, cr) - text.draw(pp.label, cr) - timeseries.draw_static(pp.plot, cr) + text.draw(pp.label, cr) + timeseries.draw_static(pp.plot, cr) end M.tagged_percent_timeseries_draw_dynamic = function(obj, cr) - text_threshold.draw(obj.value, cr) - timeseries.draw_dynamic(obj.plot, cr) + text_threshold.draw(obj.value, cr) + timeseries.draw_dynamic(obj.plot, cr) end M.tagged_percent_timeseries_set = function(obj, percent) - local _percent = pure.round_percent(percent) - text.set(obj.value, _percent) - timeseries.update(obj.plot, _percent / 100) + local _percent = pure.round_percent(percent) + text.set(obj.value, _percent) + timeseries.update(obj.plot, _percent / 100) end M.tagged_maybe_percent_timeseries_set = function(obj, percent) - if percent == false then - text.set(obj.value, -1) - timeseries.update(obj.plot, 0) - else - M.tagged_percent_timeseries_set(obj, percent) - end + if percent == false then + text.set(obj.value, -1) + timeseries.update(obj.plot, 0) + else + M.tagged_percent_timeseries_set(obj, percent) + 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 -- 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) - local num_fmt - if plot_max < 2 then - num_fmt = '%.2f' - elseif plot_max < 4 then - num_fmt = '%.1f' - else - num_fmt = '%.0f' - end - return string.format('%s %s', num_fmt, unit) + local num_fmt + if plot_max < 2 then + num_fmt = '%.2f' + elseif plot_max < 4 then + num_fmt = '%.1f' + else + num_fmt = '%.0f' + end + return string.format('%s %s', num_fmt, unit) end M.converted_y_label_format_generator = function(unit) - return function(plot_max) - local new_prefix, new_max = format.convert_data_val(plot_max) - local conversion_factor = plot_max / new_max - local fmt = M.y_label_format_string(new_max, new_prefix..unit..'/s') - return function(bytes) - return string.format(fmt, bytes / conversion_factor) - end - end + return function(plot_max) + local new_prefix, new_max = format.convert_data_val(plot_max) + local conversion_factor = plot_max / new_max + local fmt = M.y_label_format_string(new_max, new_prefix..unit..'/s') + return function(bytes) + return string.format(fmt, bytes / conversion_factor) + end + end end ----------------------------------------------------------------------------- -- tagged scaled plot M.make_tagged_scaled_timeseries = function(x, y, w, h, format_fun, label_fun, - spacing, label, min_domain, - update_freq) - return { - label = _left_text(geom.make_point(x, y), label), - value = text.make_formatted( - geom.make_point(x + w, y), - 0, - _right_text_style, - format_fun - ), - plot = _make_scaled_timeseries(x, y + spacing, w, h, label_fun, min_domain, update_freq), - } + spacing, label, min_domain, + update_freq) + return { + label = _left_text(geom.make_point(x, y), label), + value = text.make_formatted( + geom.make_point(x + w, y), + 0, + _right_text_style, + format_fun + ), + plot = _make_scaled_timeseries( + x, + y + spacing, + w, + h, + label_fun, + min_domain, + update_freq + ), + } end M.tagged_scaled_timeseries_draw_static = function(asp, cr) - text.draw(asp.label, cr) + text.draw(asp.label, cr) end M.tagged_scaled_timeseries_draw_dynamic = function(asp, cr) - text.draw(asp.value, cr) - scaled_timeseries.draw_dynamic(asp.plot, cr) + text.draw(asp.value, cr) + scaled_timeseries.draw_dynamic(asp.plot, cr) end M.tagged_scaled_timeseries_set = function(asp, value) - text.set(asp.value, value) - scaled_timeseries.update(asp.plot, value) + text.set(asp.value, value) + scaled_timeseries.update(asp.plot, value) end ----------------------------------------------------------------------------- -- rate timecourse plots local make_differential = function(update_frequency) - return function(x0, x1) - -- mask overflow - if x1 > x0 then - return (x1 - x0) * update_frequency - else - return 0 - end - end + return function(x0, x1) + -- mask overflow + if x1 > x0 then + return (x1 - x0) * update_frequency + else + return 0 + end + end end M.make_rate_timeseries = function(x, y, w, h, format_fun, label_fun, spacing, - label, min_domain, update_freq, init) - return { - label = _left_text(geom.make_point(x, y), label), - value = text.make_formatted( - geom.make_point(x + w, y), - 0, - _right_text_style, - format_fun - ), - plot = _make_scaled_timeseries(x, y + spacing, w, h, label_fun, min_domain, update_freq), - prev_value = init, - derive = make_differential(update_freq), - } + label, min_domain, update_freq, init) + return { + label = _left_text(geom.make_point(x, y), label), + value = text.make_formatted( + geom.make_point(x + w, y), + 0, + _right_text_style, + format_fun + ), + plot = _make_scaled_timeseries( + x, + y + spacing, + w, + h, + label_fun, + min_domain, + update_freq + ), + prev_value = init, + derive = make_differential(update_freq), + } end M.update_rate_timeseries = function(obj, value) - local rate = obj.derive(obj.prev_value, value) - text.set(obj.value, rate) - scaled_timeseries.update(obj.plot, rate) - obj.prev_value = value + local rate = obj.derive(obj.prev_value, value) + text.set(obj.value, rate) + scaled_timeseries.update(obj.plot, rate) + obj.prev_value = value end ----------------------------------------------------------------------------- -- circle M.make_circle = function(x, y, r) - return circle.make( - geom.make_circle(x, y, r), - circle.config(style.line(ARC_WIDTH, CAIRO_LINE_CAP_BUTT), patterns.border) - ) + return circle.make( + geom.make_circle(x, y, r), + circle.config(style.line(ARC_WIDTH, CAP_BUTT), patterns.border) + ) end ----------------------------------------------------------------------------- -- ring with text data in the center M.make_text_circle = function(x, y, r, fmt, threshhold, pre_function) - return { - ring = M.make_circle(x, y, r), - value = text_threshold.make_formatted( - geom.make_point(x, y), - 0, - text.config(normal_font_spec, patterns.text.active, 'center', 'center'), - fmt, - text_threshold.config(patterns.text.critical, threshhold, pre_function) - ), - } + return { + ring = M.make_circle(x, y, r), + value = text_threshold.make_formatted( + geom.make_point(x, y), + 0, + text.config(normal_font_spec, patterns.text.active, 'center', 'center'), + fmt, + text_threshold.config(patterns.text.critical, threshhold, pre_function) + ), + } end M.text_circle_draw_static = function(tr, cr) - arc.draw(tr.ring, cr) + arc.draw(tr.ring, cr) end M.text_circle_draw_dynamic = function(tr, cr) - text_threshold.draw(tr.value, cr) + text_threshold.draw(tr.value, cr) end M.text_circle_set = function(tr, value) - text_threshold.set(tr.value, value) + text_threshold.set(tr.value, value) end ----------------------------------------------------------------------------- -- dial local threshold_indicator = function(threshold) - return source.threshold_config( - patterns.indicator.fg.active, - patterns.indicator.fg.critical, - threshold - ) + return source.threshold_config( + patterns.indicator.fg.active, + patterns.indicator.fg.critical, + threshold + ) end M.make_dial = function(x, y, radius, thickness, threshold, _format, pre_function) - return { - dial = dial.make( - geom.make_arc(x, y, radius, DIAL_THETA0, DIAL_THETA1), - arc.config(style.line(thickness, CAIRO_LINE_CAP_BUTT), patterns.indicator.bg), - threshold_indicator(threshold) - ), - text_circle = M.make_text_circle(x, y, radius - thickness / 2 - 2, _format, threshold, pre_function), - } + return { + dial = dial.make( + geom.make_arc(x, y, radius, DIAL_THETA0, DIAL_THETA1), + arc.config(style.line(thickness, CAP_BUTT), patterns.indicator.bg), + threshold_indicator(threshold) + ), + text_circle = M.make_text_circle(x, y, radius - thickness / 2 - 2, _format, threshold, pre_function), + } end M.dial_set = function(dl, value) - dial.set(dl.dial, value) - M.text_circle_set(dl.text_circle, value) + dial.set(dl.dial, value) + M.text_circle_set(dl.text_circle, value) end M.dial_draw_static = function(dl, cr) - dial.draw_static(dl.dial, cr) - M.text_circle_draw_static(dl.text_circle, cr) + dial.draw_static(dl.dial, cr) + M.text_circle_draw_static(dl.text_circle, cr) end M.dial_draw_dynamic = function(dl, cr) - dial.draw_dynamic(dl.dial, cr) - M.text_circle_draw_dynamic(dl.text_circle, cr) + dial.draw_dynamic(dl.dial, cr) + M.text_circle_draw_dynamic(dl.text_circle, cr) end ----------------------------------------------------------------------------- -- compound dial M.make_compound_dial = function(x, y, outer_radius, inner_radius, thickness, - threshold, num_dials) - return compound_dial.make( - geom.make_arc(x, y, outer_radius, DIAL_THETA0, DIAL_THETA1), - arc.config(style.line(thickness, CAIRO_LINE_CAP_BUTT), patterns.indicator.bg), - threshold_indicator(threshold), - inner_radius, - num_dials - ) + threshold, num_dials) + return compound_dial.make( + geom.make_arc(x, y, outer_radius, DIAL_THETA0, DIAL_THETA1), + arc.config(style.line(thickness, CAP_BUTT), patterns.indicator.bg), + threshold_indicator(threshold), + inner_radius, + num_dials + ) end ----------------------------------------------------------------------------- -- annotated compound bar M.make_compound_bar = function(x, y, w, pad, labels, spacing, thickness, threshold) - return { - labels = text_column.make( - geom.make_point(x, y), - labels, - _left_text_style, - nil, - spacing - ), - bars = compound_bar.make( - geom.make_point(x + pad, y), - w - pad, - line.config( - style.line(thickness, CAIRO_LINE_CAP_BUTT), + return { + labels = text_column.make( + geom.make_point(x, y), + labels, + _left_text_style, + nil, + spacing + ), + bars = compound_bar.make( + geom.make_point(x + pad, y), + w - pad, + line.config( + style.line(thickness, CAP_BUTT), patterns.indicator.bg, true - ), - threshold_indicator(threshold), - spacing, - #labels, - false - ) - } + ), + threshold_indicator(threshold), + spacing, + #labels, + false + ) + } end M.compound_bar_draw_static = function(cb, cr) - text_column.draw(cb.labels, cr) - compound_bar.draw_static(cb.bars, cr) + text_column.draw(cb.labels, cr) + compound_bar.draw_static(cb.bars, cr) end M.compound_bar_draw_dynamic = function(cb, cr) - compound_bar.draw_dynamic(cb.bars, cr) + compound_bar.draw_dynamic(cb.bars, cr) end M.compound_bar_set = function(cb, i, value) - compound_bar.set(cb.bars, i, value) + compound_bar.set(cb.bars, i, value) end ----------------------------------------------------------------------------- -- separator (eg a horizontal line) M.make_separator = function(x, y, w) - return line.make( - _make_horizontal_line(x, y, w), - line.config( - style.line(SEPARATOR_THICKNESS, CAIRO_LINE_CAP_BUTT), - patterns.border, - true - ) - ) + return line.make( + _make_horizontal_line(x, y, w), + line.config( + style.line(SEPARATOR_THICKNESS, CAP_BUTT), + patterns.border, + true + ) + ) end ----------------------------------------------------------------------------- -- text row (label with a value, aligned as far apart as possible) M.make_text_row = function(x, y, w, label) - return { - label = _left_text(geom.make_point(x, y), label), - value = _right_text(geom.make_point(x + w, y), nil), - } + return { + label = _left_text(geom.make_point(x, y), label), + value = _right_text(geom.make_point(x + w, y), nil), + } end M.text_row_draw_static = function(row, cr) - text.draw(row.label, cr) + text.draw(row.label, cr) end M.text_row_draw_dynamic = function(row, cr) - text.draw(row.value, cr) + text.draw(row.value, cr) end M.text_row_set = function(row, value) - text.set(row.value, value) + text.set(row.value, value) end ----------------------------------------------------------------------------- -- text row with critical indicator M.make_threshold_text_row = function(x, y, w, label, append_end, limit) - return{ - label = _left_text(geom.make_point(x, y), label), - value = text_threshold.make_formatted( - geom.make_point(x + w, y), - nil, - _right_text_style, - append_end, - text_threshold.config(patterns.text.critical, limit, false) - ) - } + return{ + label = _left_text(geom.make_point(x, y), label), + value = text_threshold.make_formatted( + geom.make_point(x + w, y), + nil, + _right_text_style, + append_end, + text_threshold.config(patterns.text.critical, limit, false) + ) + } end M.threshold_text_row_draw_static = M.text_row_draw_static M.threshold_text_row_draw_dynamic = function(row, cr) - text_threshold.draw(row.value, cr) + text_threshold.draw(row.value, cr) end M.threshold_text_row_set = function(row, value) - text_threshold.set(row.value, value) + text_threshold.set(row.value, value) end ----------------------------------------------------------------------------- -- multiple text row separated by spacing - M.make_text_rows_formatted = function(x, y, w, spacing, labels, format) - return { - labels = text_column.make( - geom.make_point(x, y), - labels, - _left_text_style, - nil, - spacing - ), - values = text_column.make_n( - geom.make_point(x + w, y), - #labels, - _right_text_style, - format, - spacing, - 0 - ) - } + M.make_text_rows_formatted = function(x, y, w, spacing, labels, _format) + return { + labels = text_column.make( + geom.make_point(x, y), + labels, + _left_text_style, + nil, + spacing + ), + values = text_column.make_n( + geom.make_point(x + w, y), + #labels, + _right_text_style, + _format, + spacing, + 0 + ) + } end M.make_text_rows = function(x, y, w, spacing, labels) - return M.make_text_rows_formatted( - x, - y, - w, - spacing, - labels, - nil - ) + return M.make_text_rows_formatted( + x, + y, + w, + spacing, + labels, + nil + ) end M.text_rows_draw_static = function(rows, cr) - text_column.draw(rows.labels, cr) + text_column.draw(rows.labels, cr) end M.text_rows_draw_dynamic = function(rows, cr) - text_column.draw(rows.values, cr) + text_column.draw(rows.values, cr) end M.text_rows_set = function(rows, i, value) - text_column.set(rows.values, i, value) + text_column.set(rows.values, i, value) end ----------------------------------------------------------------------------- -- 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 col_fmt = gtable.name_chars > 0 and gtable.name_chars + local default_table_config = function(label) - return tbl.config( - rect.config( - style.closed_poly(TABLE_LINE_THICKNESS, CAIRO_LINE_JOIN_MITER), - patterns.border - ), - line.config( - style.line(TABLE_LINE_THICKNESS, CAIRO_LINE_CAP_BUTT), - patterns.border, - true - ), - tbl.header_config( - default_table_font_spec, - patterns.text.active, - TABLE_HEADER_PAD - ), - tbl.body_config( - default_table_font_spec, - patterns.text.inactive, - { - tbl.column_config('Name', TABLE_BODY_FORMAT), + return tbl.config( + rect.config( + style.closed_poly(TABLE_LINE_THICKNESS, JOIN_MITER), + patterns.border + ), + line.config( + style.line(TABLE_LINE_THICKNESS, CAP_BUTT), + patterns.border, + true + ), + tbl.header_config( + default_table_font_spec, + patterns.text.active, + gtable.header_padding + ), + tbl.body_config( + default_table_font_spec, + patterns.text.inactive, + { + tbl.column_config('Name', col_fmt), tbl.column_config('PID', false), tbl.column_config(label, false), - } - ), - tbl.padding( - 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) - ) + } + ), + tbl.padding(xpad, ypad, xpad, ypad) + ) end 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 ----------------------------------------------------------------------------- -- panel M.make_panel = function(x, y, w, h, thickness) - return fill_rect.make( - geom.make_box(x, y, w, h), - rect.config( - style.closed_poly(thickness, CAIRO_LINE_JOIN_MITER), - patterns.border - ), - patterns.panel.bg - ) + return fill_rect.make( + geom.make_box(x, y, w, h), + rect.config( + style.closed_poly(thickness, JOIN_MITER), + patterns.border + ), + patterns.panel.bg + ) end - ---------------------------------------------------------------------------- -- compile individual module diff --git a/drawing/memory.lua b/drawing/memory.lua index 262fc56..56dd1c0 100644 --- a/drawing/memory.lua +++ b/drawing/memory.lua @@ -179,7 +179,6 @@ return function(update_freq, config, common, width, point) local mk_tbl = function(y) local num_rows = config.table_rows - local table_height = common.table_height(num_rows) local table_conky = pure.map_n( function(i) return { @@ -193,7 +192,6 @@ return function(update_freq, config, common, width, point) point.x, y, width, - table_height, num_rows, 'Mem (%)' ) @@ -206,7 +204,7 @@ return function(update_freq, config, common, width, point) end return common.mk_acc( width, - table_height, + common.table_height(num_rows), update, pure.partial(text_table.draw_static, obj), pure.partial(text_table.draw_dynamic, obj) diff --git a/drawing/power.lua b/drawing/power.lua index 8906e80..dcd7254 100644 --- a/drawing/power.lua +++ b/drawing/power.lua @@ -112,8 +112,7 @@ return function(update_freq, config, common, width, point) set_state = nil, top = pure.concat( pure.map(mk_rate_blockspec, config.rapl_specs), - -- TODO what happens if this is nil? - {{mk_bat, config.battery ~= nil, 0}} + {{mk_bat, config.battery ~= '', 0}} ) } end diff --git a/drawing/processor.lua b/drawing/processor.lua index 20a7575..428fb99 100644 --- a/drawing/processor.lua +++ b/drawing/processor.lua @@ -193,7 +193,6 @@ return function(update_freq, config, main_state, common, width, point) local mk_tbl = function(y) local num_rows = config.table_rows - local table_height = common.table_height(num_rows) local table_conky = pure.map_n( function(i) return {pid = '${top pid '..i..'}', cpu = '${top cpu '..i..'}'} end, num_rows @@ -202,7 +201,6 @@ return function(update_freq, config, main_state, common, width, point) point.x, y, width, - table_height, num_rows, 'CPU (%)' ) @@ -218,7 +216,7 @@ return function(update_freq, config, main_state, common, width, point) end return common.mk_acc( width, - table_height, + common.table_height(num_rows), update, pure.partial(text_table.draw_static, tbl), pure.partial(text_table.draw_dynamic, tbl) diff --git a/drawing/system.lua b/drawing/system.lua index 39238ae..123b44b 100644 --- a/drawing/system.lua +++ b/drawing/system.lua @@ -14,6 +14,8 @@ return function(main_state, common, width, point) TEXT_SPACING, {'Kernel', 'Uptime', 'Last Upgrade', 'Last Sync'} ) + -- just update this once + common.text_rows_set(obj, 1, i_o.conky('$kernel')) local update = function() local last_update, last_sync if main_state.pacman_stats then @@ -22,8 +24,6 @@ return function(main_state, common, width, point) "^%d+%s+([^%s]+)%s+([^%s]+).*" ) 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, 3, last_update) common.text_rows_set(obj, 4, last_sync) diff --git a/schema.yml b/schema.yml index 7607cd5..f2ce938 100644 --- a/schema.yml +++ b/schema.yml @@ -71,10 +71,8 @@ properties: additionalProperties: false properties: battery: - description: the battery device to use (if applicable) - anyOf: - - type: string - - type: "null" + description: the battery device to use (or blank if none) + type: string rapl_specs: description: the Intel RAPL specs for which plots should be made type: array @@ -181,7 +179,7 @@ properties: network|pacman|filesystem|power|memory$" theme: - required: [font, patterns] + required: [font, geometry, patterns] additionalProperties: false properties: font: @@ -200,6 +198,66 @@ properties: plot_label: *font_size table: *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: required: [header, panel, text, border, plot, indicator] additionalProperties: false @@ -215,10 +273,10 @@ properties: properties: color: type: integer - alpha: - anyOf: - - type: "null" - - &alpha {type: number, minimum: 0, maximum: 1} + alpha: &alpha + type: number + minimum: 0 + maximum: 1 gradient: type: array minItems: 2