It is currently December 15th, 2018, 12:43 pm

If / Then / Else with Conditional Operators in Rainmeter

Our most popular Tips and Tricks from the Rainmeter Team and others
User avatar
jsmorley
Developer
Posts: 18500
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

If / Then / Else with Conditional Operators in Rainmeter

jsmorley » June 12th, 2013, 3:39 pm

One of the things folks run into when creating skins is that the IfActions functionality, while powerful, has some limitations.

Code: Select all

[MeasureCond]
Measure=Calc
Formula=50
IfAboveValue=50
IfAboveAction=[!SetOption MeterCond Text "I'm above 50"]
IfBelowValue=50
IfBelowAction=[!SetOption MeterCond Text "I'm below 50"]
IfEqualValue=50
IfEqualAction=[!SetOption MeterCond Text "I'm exactly 50"]
The limitation is that there can only be one of each of the three IfActions, (IFBelow, IfEqual, IfAbove) so it is not possible to say "if I am above 50 do A, if I am above 60 do B". Since there can only be one IfAboveValue option, the answer to this will have to be "A", even if the value being compared is 70.

The solution to this is to explore the use of conditional operations in a formula in Rainmeter. We will focus on using them in Calc measures for purposes of this guide.

The conditional operation in Rainmeter is a way to have a more complex "If / Then / ElseIf / Then / Else" comparison, allowing you to set the value of the measure based on a broad range of comparisons. You can then use IfActions on the measure to take actions, or Substitute to change the number value into some text you might use in a meter later.

The form of the conditional operation is condition ? expression if true : expression if false. When the "condition" is evaluated, it is either "true" or "false". When it is "true", the expression after the "?" is evaluated. If it is "false", the expression after the ":" is done. This is equivalent to a block like this in a programming language:

Code: Select all

 if (condition)
     then
       expr. if true
     else
       expr. if false
   end if


Let's start with a simple example:

Code: Select all

[Val]
Measure=Calc
Formula=50

[MeasureCond]
Measure=Calc
Formula=Val > 49 ? 1 : -1
[MeasureCond] will be 1

What this is doing is asking "is [Val] greater than 49?". If it is, the the condition is "true", and the value of this Calc measure is set to "1" (the "then" part of the formula). If it is not true, then the value is set to "-1" (the "else" part of the formula).

I'm just using a simple Calc measure [Val] to set a value we can use for our comparison. Normally you are going to be comparing with some measure that is returning some value based on a measurement.

It should be noted as we get started that there must always be all three parts of the formula. This whole thing is known in programming languages as a "Ternary Operation", which comes from the Latin for "three operations". You must always have an "if" a "then" and an "else" or an error will result.

Now this isn't much different than just using an IfAction right on the [Val] measure like "IfAboveValue=49", but I wanted to start simple and work up to more complex examples that go beyond what an IfAction is capable of.

You can use formulas in the condition part of the formula as well:

Code: Select all

[MeasureCond]
Measure=Calc
Formula=Val * 2 = 100 ? 1 : -1
With [Val] still set to 50, [MeasureCond] will be 1

You can use Section Variables as well. Just be sure to set DynamicVariables=1 on the measure to use the current value:

Code: Select all

[Val]
Measure=Calc
Formula=50

[Val2]
Measure=Calc
Formula=40

[MeasureCond]
Measure=Calc
Formula=Val > [Val2] ? 1 : -1
DynamicVariables=1
Since the value of [Val] is larger than the value of [Val2], [MeasureCond] will be 1

Or you can use formulas or Section Variables in the "then" or "else" parts as well:

Code: Select all

[MeasureCond]
Measure=Calc
Formula=Val > 50 ? 1 : [Val]
DynamicVariables=1
Since the value of [Val] is 50, the condition is "false" and [MeasureCond] is set to the value of [Val] instead of "1"

You can also use compound conditions using things like AND and OR.

Code: Select all

[Val]
Measure=Calc
Formula=50

[MeasureCond]
Measure=Calc
Formula=(Val > 49) && (Val < 60) ? 1 : -1

[MeasureCond2]
Measure=Calc
Formula=(Val = 50) || (Val = 100) ? 1 : -1
These are using the "logical AND" and "logical OR". Note that you must enclose the components of the condition in parentheses. In both cases, [MeasureCond] and [MeasureCond2], the result is "1"

We should stop for one second and touch on terminology.

(parentheses)
[brackets]
{braces}

Don't confuse parentheses with brackets or braces, or I will just send you to visit Grammar Girl ;-)

Ok, that should touch on most of the simple uses, things that you can also logically get to with IfActions in most cases. Now let's look at how we can use "nesting" of "If / Then / ElseIf / Then / Else" to get the full benefit of conditional operations.

Code: Select all

[Val]
Measure=Calc
Formula=50

[MeasureCond]
Measure=Calc
Formula=Val > 74 ? 4 : (Val > 49 ? 3 : (Val > 24 ? 2 : 1))
Let's look at what this is saying. It is in effect walking through a series of "If / Then" statements, stopping when the result is "true" and continuing to evaluate the next "Else" when the result is "false". At the very end is the last "Else", in this example : 1, which will be the value if the entire expression is never "true".

"Is Val greater than 74? No. Well then, is Val greater than 49? Yes!" So the value of [MeasureCond] will be "3".

Important Notes: You must use parentheses to "nest" the conditional operations within the whole of the expression. So each of the "If" conditions after the initial one would start with an open parentheses, and you would put as many end parentheses at the very end of the entire option as there are "If" conditions after the first one. Look carefully at the Formula above to see how this should be done. Also, there is a limit of 30 nested operations in a single formula in Rainmeter.

If the Formula was more complex, with more "ElseIf" comparisons, it might look like this:

Code: Select all

Formula=Val > 90 ? 9 : (Val > 80 ? 8 : (Val > 70 ? 7 : (Val > 60 ? 6 : (Val > 50 ? 5 : (Val > 40 ? 4 : (Val > 30 ? 3 : (Val > 20 ? 2 : (Val > 10 ? 1 : 0))))))))
Eight starting parentheses to begin each "If", and eight ending parentheses at the very end to "close" them all.

Using the result:

You can certainly directly use the value of [MeasureCond] (in our examples) directly as MeasureName in a meter or as a Section Variable in other measures or meters.

You can also use IfActions on the measure to take actions as long as the result lends itself to the limitations of IfActions:

Code: Select all

[Val]
Measure=Calc
Formula=50

[MeasureCond]
Measure=Calc
Formula=Val * 2 = 100 ? 1 : -1
IfEqualValue=1
IfEqualAction=[!SetOption MeterCond Text "I'm One"]
IfBelowValue=0
IfBelowAction=[!SetOption MeterCond Text "I'm Negative"]
Or use a Substitute to turn the numeric value into some text you can use in a meter:

Code: Select all

[Val]
Measure=Calc
Formula=50

[MeasureCond]
Measure=Calc
Formula=Val > 74 ? 4 : (Val > 49 ? 3 : (Val > 24 ? 2 : 1))
Substitute="4":"Last Quarter","3":"Third Quarter","2":"Second Quarter","1":"First Quarter"
Remember our example of the limitations of IfAction from the very beginning of this guide?

Code: Select all

[Val]
Measure=Calc
Formula=70
The limitation is that there can only be one of each of the three IfActions, (IFBelow, IfEqual, IfAbove) so it is not possible to say "if I am above 50 do A, if I am above 60 do B". Since there can only be one IfAboveValue option, the answer to this will have to be "A", even if the value being compared is 70.

Using a Calc measure with a nested conditional operation, we can in fact bend the IfAction to our will:

Code: Select all

[MeasureCond]
Measure=Calc
Formula=Val > 60 ? 2 : (Val > 50 ? 1 : -1)
IfEqualValue=1
IfEqualAction=[!SetOption MeterCond Text "I'm above 50"]
IfAboveValue=1
IfAboveAction=[!SetOption MeterCond Text "I'm above 60"]
IfBelowValue=0
IfBelowAction=[!SetOption MeterCond Text "I'm below 50"]
Extra credit:

I mentioned that I would be using Calc measures to demonstrate how conditional operations work, but it should be noted that they will work anywhere a formula is allowed!

Code: Select all

[MeterImage]
Meter=Image
W=10
H=10
SolidColor=0,0,0,255
X=(#SCREENAREAWIDTH# = 1680 ? 160 : (#SCREENAREAWIDTH# = 1280 ? 128 : 0))
Y=0
Just remember that outside of a Calc measure, formulas must be totally enclosed in starting and ending parentheses, aside from any you might need for "nesting".


Hope this is of some help with understanding this feature of Rainmeter.
User avatar
jumper77
Posts: 132
Joined: October 13th, 2016, 2:07 am

Re: If / Then / Else with Conditional Operators in Rainmeter

jumper77 » October 26th, 2016, 1:29 pm

What a wealth of information!! These examples are great. Being new to Rainmeter, I have looked for a way to do all the things you presented. This will help a lot.

Thank you for this guide.
USING: Rainmeter 4.0 Beta Release
User avatar
Mor3bane
Posts: 558
Joined: May 7th, 2016, 7:32 am

Re: If / Then / Else with Conditional Operators in Rainmeter

Mor3bane » June 1st, 2018, 11:10 am

I Finally understand the nesting and the syntax for inline if then tests!

Thanks!
:17good
My DevArt Gallery

There are many ways to be different - there is only one way to be yourself