SimpleConkyScript/lua/drawing.lua

298 lines
9.5 KiB
Lua

-- HorlogeSkynet's Lua script (for Conky) -- Drawing module
-- <https://git.forestier.app/HorlogeSkynet/SimpleConkyScript.git>
local drawing = {}
-- `config` object is passed as parameter here.
local _settings = (...).get_entries('settings')
-- Quick hack to stay compatible across multiple Lua versions.
local unpack = unpack or table.unpack
-- Generic function to draw our 'graph' objects.
function drawing.graph(display, x_pos, y_pos, width, text, values, color)
local HEIGHT = 25
local LINE_WIDTH = 4
-- SimpleConkyScript v3 : The maximum number of values directly depends on the graph width.
local NUMBER_MAX_VALUES = (width / LINE_WIDTH)
-- Display the associated 'text' object first.
y_pos = drawing.text(display, x_pos, y_pos, text)
-- We apply the globally set padding between 'text' and 'bar'.
y_pos = y_pos + _settings.display.entity_padding
local count = #values
if count == 0 then return y_pos + HEIGHT end
-- When specified, set a specific color.
if color then
cairo_set_source_rgba(display, unpack(color))
end
if count > NUMBER_MAX_VALUES then
table.remove(values, 1)
count = count - 1
end
local max_of_value = values[1]
for i = 2, count do
if values[i] > max_of_value then max_of_value = values[i] end
end
if max_of_value == 0 then max_of_value = 1 end
cairo_set_line_width(display, LINE_WIDTH)
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
local current_x_pos = x_pos + width - (LINE_WIDTH / 2.)
local value
for i = 1, count do
value = values[count - i + 1]
cairo_move_to(display, current_x_pos, y_pos + (1 - value / max_of_value) * HEIGHT)
cairo_line_to(display, current_x_pos, y_pos + HEIGHT)
current_x_pos = current_x_pos - LINE_WIDTH
end
cairo_stroke(display)
-- If a color has been specified, simply reset palette for future drawings.
if color then
cairo_set_source_rgba(display, unpack(_settings.colors.default))
end
return y_pos + HEIGHT
end
-- Generic function to draw our 'text' objects (potentially centered).
function drawing.text(display, x_pos, y_pos, text, width_alignment)
if width_alignment then
-- Quick-and-dirty center alignment computation.
-- This is based on the assumption that we're using a "Monospaced" font.
-- See <https://en.wikipedia.org/wiki/Monospaced_font> for further information.
local MAGIC_RATIO = (_settings.font.size * 0.6) / 2.
x_pos = x_pos + (width_alignment / 2.) - (#text * MAGIC_RATIO)
end
y_pos = y_pos + _settings.font.size
cairo_move_to(display, x_pos, y_pos)
cairo_show_text(display, text)
cairo_stroke(display)
return y_pos
end
-- Specific function to draw our 'text' objects (centered in columns).
function drawing.text_in_column(display, x_pos, y_pos, text, align_center)
return drawing.text(
display,
x_pos, y_pos,
text,
(align_center and _settings.display.columns_width))
end
-- Generic function to draw our 'bar' objects.
function drawing.bar(display, x_pos, y_pos, value, text, show_percent)
local LINE_WIDTH = 5
local CURSOR_WIDTH = 5
local CURSOR_HEIGHT = 10
-- When specified, add the percentage value as text.
if show_percent then
text = string.format("%s (%d%%)", text, value)
end
-- Display the associated 'text' object first.
y_pos = drawing.text(display, x_pos, y_pos, text)
-- We apply the globally set padding between 'text' and 'bar'.
y_pos = y_pos + _settings.display.entity_padding
y_pos = y_pos + (LINE_WIDTH / 2.)
local begin_x, cursor_x, end_x =
x_pos,
x_pos + (CURSOR_WIDTH / 2.) + (value / 100.) * (_settings.display.columns_width - CURSOR_WIDTH),
x_pos + _settings.display.columns_width
cairo_set_line_width(display, LINE_WIDTH)
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
-- Beginning of the line.
cairo_move_to(display, begin_x, y_pos)
cairo_line_to(display, cursor_x, y_pos)
cairo_stroke(display)
-- Ending of the line (apply user-defined "background" color).
cairo_set_source_rgba(display, unpack(_settings.colors.bar_background))
cairo_move_to(display, cursor_x, y_pos)
cairo_line_to(display, end_x, y_pos)
cairo_stroke(display)
-- Just get back to the default color.
cairo_set_source_rgba(display, unpack(_settings.colors.default))
-- Cursor.
cairo_set_line_width(display, CURSOR_WIDTH)
y_pos = y_pos - (LINE_WIDTH / 2.)
cairo_move_to(display, cursor_x, y_pos)
y_pos = y_pos + CURSOR_HEIGHT
cairo_line_to(display, cursor_x, y_pos)
cairo_stroke(display)
return y_pos
end
-- Specific function to draw our section separation.
function drawing.section_separation(display, x_pos, y_pos, width)
local SEPARATION_HEIGHT = 3
-- Check (and potentially tweak) `width` parameter.
if not width then
width = 0.5
elseif width < 0 then
width = 0
elseif width > 1 then
width = 1
end
local begin_x = x_pos + (_settings.display.columns_width * (1 - width) / 2.)
local end_x = begin_x + (_settings.display.columns_width * width)
-- The separation line will add top padding itself.
y_pos = y_pos + _settings.display.entity_padding + (SEPARATION_HEIGHT / 2.)
cairo_set_line_width(display, SEPARATION_HEIGHT)
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
cairo_move_to(display, begin_x, y_pos)
cairo_line_to(display, end_x, y_pos)
cairo_stroke(display)
return y_pos + (SEPARATION_HEIGHT / 2.)
end
-- Specific function to draw a clock.
-- Taken from <https://github.com/brndnmtthws/conky/wiki/Using-Lua-scripts-(Part-12)%3A-Clock-and-circular-things>.
function drawing.clock(display, x_pos, y_pos)
local CLOCK_RADIUS = 60
local CLOCK_BORDER_WIDTH = 2
local GAP_BORDER_HOUR_MARKS = 5
local MARK_WIDTH = 3
local MARK_LENGTH = 10
local SECOND_HAND_WIDTH = 1
local SECOND_HAND_LENGTH = 50
local MINUTE_HAND_WIDTH = 3
local MINUTE_HAND_LENGTH = 40
local HOUR_HAND_WIDTH = 5
local HOUR_HAND_LENGTH = 30
-- Plain maths: `2 * PI / 360`.
local DEGREE_TO_RADIAN = (math.pi / 180.)
local MARK_END_RAD = CLOCK_RADIUS - GAP_BORDER_HOUR_MARKS
local MARK_START_RAD = MARK_END_RAD - MARK_LENGTH
local clock_center_x = x_pos + (_settings.display.columns_width / 2.)
local clock_center_y = y_pos + CLOCK_RADIUS + CLOCK_BORDER_WIDTH
cairo_set_line_width(display, CLOCK_BORDER_WIDTH)
cairo_arc(display, clock_center_x, clock_center_y, CLOCK_RADIUS, 0, 2 * math.pi)
cairo_stroke(display)
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_set_line_width(display, MARK_WIDTH)
local point, radius, x, y
for i = 1, 12 do
point, radius = DEGREE_TO_RADIAN * ((i - 1) * 30), MARK_START_RAD
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_move_to(display, clock_center_x + x, clock_center_y + y)
radius = MARK_END_RAD
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_stroke(display)
end
local hours = tonumber(os.date('%I'))
-- Plain maths: `3600 = 60 * 60`.
local hours_to_second = hours * 3600
local minutes = tonumber(os.date('%M'))
local minutes_to_seconds = minutes * 60
local seconds = tonumber(os.date('%S'))
local hours_seconds = hours_to_second + minutes_to_seconds + seconds
-- Plain maths: `(1 / 120) = 360 / (60 * 60 * 12)`.
local hours_seconds_degrees = hours_seconds / 120.
cairo_move_to(display, clock_center_x, clock_center_y)
point, radius = DEGREE_TO_RADIAN * hours_seconds_degrees, HOUR_HAND_LENGTH
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_set_line_width(display, HOUR_HAND_WIDTH)
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_stroke(display)
local minutes_seconds = minutes_to_seconds + seconds
local minutes_seconds_degrees = minutes_seconds * 0.1
cairo_move_to(display, clock_center_x, clock_center_y)
point, radius = DEGREE_TO_RADIAN * minutes_seconds_degrees, MINUTE_HAND_LENGTH
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_set_line_width(display, MINUTE_HAND_WIDTH)
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_stroke(display)
local seconds_degrees = seconds * 6
cairo_move_to(display, clock_center_x, clock_center_y)
point, radius = DEGREE_TO_RADIAN * seconds_degrees, SECOND_HAND_LENGTH
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_set_line_width(display, SECOND_HAND_WIDTH)
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_set_source_rgba(display, unpack(_settings.colors.clock_second_hand))
cairo_stroke(display)
-- Just get back to the default color.
cairo_set_source_rgba(display, unpack(_settings.colors.default))
-- This part has been added to the original snippet.
-- It designs a filled circle to be set at the center of the clock, above the hands.
cairo_arc(display, clock_center_x, clock_center_y, HOUR_HAND_WIDTH * 1.25, 0, 2 * math.pi)
cairo_fill(display)
-- -------------------------------------------------
return y_pos + (2 * CLOCK_RADIUS) + (2 * CLOCK_BORDER_WIDTH)
end
return drawing