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