298 lines
9.5 KiB
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
|