Using Lua scripts (Part 06): Borders and if statements - brndnmtthws/conky GitHub Wiki
vi: Some more drawing calculations and if statements
So we have our bar indicator.
I have moved the value setting and max_value setting up into the
settings part of the code and put "bar_
" in front of each just to
keep to my naming convention :).
-- SETTINGS FOR CPU INDICATOR BAR
bar_bottom_left_x = 750
bar_bottom_left_y = 200
bar_width = 30
bar_height = 100
bar_value = tonumber (conky_parse ("${cpu}"))
bar_max_value = 100
-- Set bar background colors, 1, 0, 0, 1 = fully opaque red.
bar_bg_red = 1
bar_bg_green = 0
bar_bg_blue = 0
bar_bg_alpha = 1
-- Set indicator colors, 1, 1, 1, 1 = fully opaque white.
bar_in_red = 1
bar_in_green = 1
bar_in_blue = 1
bar_in_alpha = 1
-- END OF SETTINGS
-- DRAW BAR INDICATOR
-- Draw background.
cairo_set_source_rgba (cr, bar_bg_red, bar_bg_green, bar_bg_blue, bar_bg_alpha)
cairo_rectangle (cr, bar_bottom_left_x, bar_bottom_left_y,
bar_width, -bar_height)
cairo_fill (cr)
-- Draw indicator.
cairo_set_source_rgba (cr, bar_in_red, bar_in_green, bar_in_blue,
bar_in_alpha) -- Set indicator color.
scale = bar_height / bar_max_value
indicator_height = scale * bar_value
cairo_rectangle (cr, bar_bottom_left_x, bar_bottom_left_y,
bar_width, -indicator_height)
cairo_fill (cr)
But we want to jazz it up a bit and add a few additional features.
- We want the ability to draw a border around our indicator.
- We want the border to be optional.
- We want the ability to set the border color and border line thickness.
- We want the ability to set an "alarm" value for the bar so that:
- when the value we feed the bar bar reaches or goes past a certain point the bar changes to a different color.
- we want to be able to specify the alarm value and the color the bar changes to.
Adding an border
In our settings section we need some new options.
bar_border = 1 -- Set 1 for border or 0 for no border.
-- Set border color rgba.
border_red = 0
border_green = 1
border_blue = 1
border_alpha = 1
-- Set border thickness.
border_width = 10
I tend to use number switches for options like this, 1 = " yes, I want
it"; 0 = "no, I don't". But you could just as well use text answers
(bar_border="yes" -- set "yes" for border or "no" for no border
).
The downside is that "Yes" is not the same as "yes" when we come to
use a comparison later on.
This case specificity can be overcome by using the in built commands
string.upper ()
or string.lower ()
but that would be a topic for
another time :). For now we will use either 1 or 0
Another aspect of the border is that it shouldn't cover up any part of the indicator bar. There are actually several ways I can think of achieving the desired border
We could draw a filled in rectangle behind the indicator background rectangle. However, our "border" rectangle would be larger than the indicator rectangles, so you would see its edges sticking out around the edges of the indicator.
Or we could use the rectangle command with cairo_stroke
so that we
only draw the lines and don't fill it in.
Or we could draw individual lines.
Each of these methods has some positives and negatives, but lets go
with drawing a rectangle with cairo_stroke
.
The tricky part here is how line_width
is applied when drawing the
rectangle
(https://github.com/brndnmtthws/conky/extras/wiki/LuaTut/stroke.png).
All 3 of these rectangles have been set a width of 60 and a height of
40. The difference you see is that they have line widths of 1, 10 and
20 respectively.
We need to compensate for the encroachment of the border into the middle of our rectangle. This is how I would do it.
First we need to set the x and y coordinates for our border relative
to bar_bottom_left_x
and bar_bottom_left_y
so that when we want to
move our bar around we only need to edit bar_bottom_left_x
and
bar_bottom_left_y
and all other strings change automatically in
relation to those settings.
-- We [u]subtract[/u] because we are going to the [u]left[/u]
border_bottom_left_x = bar_bottom_left_x - (border_width / 2)
-- We [u]add[/u] because we are going [u]down[/u]
border_bottom_left_y = bar_bottom_left_y + (border_width / 2)
This starts our border rectangle to the left and lower than we start our bar to compensate for line_width. Now we also have to make the border rectangle wider and bigger than our bar rectangle so that it surrounds the bar rectangle.
brec_width = bar_width + border_width
brec_height = bar_height + border_width
NOTE: when I was writing the above lines, I thought that since I
had named the width and length strings for the indicator rectangles
bar_width
and bar_height
that I would call the width and height
strings for the border rectangle border_width
and border_height
(even had these typed out).
BUT I realised that I couldn't use border_width
because I have
already used it to name the string that holds the value of
line_width
for the border, so I had to come up with something else.
And we can set up our border and plug those strings into the rectangle drawing command like so:
cairo_set_source_rgba (cr, border_red, border_green, border_blue, border_alpha)
cairo_set_line_width (cr, border_width)
border_bottom_left_x = bar_bottom_left_x - (border_width / 2)
border_bottom_left_y = bar_bottom_left_y + (border_width / 2)
brec_width = bar_width + border_width
-- Remember that we need to make the value of brec_height negative at some.
-- point because we are drawing up.
brec_height = bar_height + border_width
-- We will set brec_height negative in this line.
cairo_rectangle (cr, border_bottom_left_x, border_bottom_left_y, brec_width,
-brec_height)
cairo_stroke (cr)
Where should we put this code?
Since we have done our calculations correctly, the border shouldn't interfere with our indicator, meaning you could have this code in several places: before we draw the background, after the background and before the indicator or after the indicator.
So we have a border but we haven't used the setting "bar_border" to allow us to optionally have the border or not. To do that we need an if statement.
IF STATEMENTS
For example:
if bar_border == 1 then
-- Border drawing code.
end
This is the simplest form of the if statement. If
the string bar_border
has a value of 1 then everything between the
then and end is done.
If we set bar_border to 0 (or if bar_border
is set to anything
other than 1 in this case) then the border doesn't get drawn
(anything between then and end is skipped).
EVERY IF NEEDS AN END. You could also say that every if needs a then but, depending on how you set up your statement, there can be multiple thens within it.
NOTE, we need a double equals sign (==) when we are making a comparison, not just one. One alone means you are asigning a variable a value.
Other options for comparisons are:
- > Greater than
- >= Greater than or equal to
- < Less than
- <= Less than or equal to
- ~= Not equal to
We will get to a more complicated if later on