Conditional Visibility

Introduction
Recently, we've been modularising much of the code that controls when items should be rendered, and when they should be left as-is.

All controls can now benefit from “conditional visibility” support. This means that, instead of specifying just “yes” or “no” for the tag, you can now provide one of the many preset boolean conditions. Not only that, you can also specify how XBMC should transistion between a visible state and a hidden state.

For example, the Project Mayhem 3 skin has  !Player.HasMedia  tags on all the background images on the home page. The reason is that we don't want the images being displayed while a media file (audio or video) is playing or paused, as the video or visualisation will cover the images anyway, so they only take up memory unnecessarily. They also slow down navigation, as the need to be loaded/unloaded depending on whether they are visible (ie whether or not the user has a particular button focused).

How They Work
The condition given in the tag is evaluated at during the control's Render function. XBMC decides whether or not the condition is true, and updates the control's visibility accordingly. Thus, it all happens without XBMC having to do the extra chores of maintaining which controls need to be shown at which points in time. The controls automatically update themselves.

Conditional Visibility for Dialogs
Dialogs can also be made to popup automatically based on a visibility condition. This is done by supplying the tag at the top of the window file (where the , and tags are). XBMC once again evaluates this visibility at render time, and if needbe, will create and show the dialog at the appropriate time. It'll also close them once that visibility has vanished.

This only works with dialogs. For custom windows, you can specify the type of window you require by specifying it using the tag. For more information see the window .xml structure page.

Combining Conditions
You can combine two (or more) of the above settings by using "+" as an AND operator, "|" as an OR operator, “!" as a NOT operator, and "[" and "]" to bracket expressions. For example, Player.HasVideo + Player.Rewinding8x will only show the control when the player is rewinding a video at 8x, whereas Player.HasVideo | Player.IsRecording will show the control if a video is playing, or if we are recording something. The AND operator takes precedence over the OR operator when evaluating the logic, and operators are read from left to right. So if you want to show something when condition1 OR condition2 is true AND condition3 is true, you can do:

[condition1 | condition2] + condition3

Note that if you missed the brackets, then it would actually be reading «if condition1 or (condition2 and condition3)" due to AND taking precedence over OR.

Some pointers on boolean logic:

The following holds true:

A + (B | C) = A + B| A + C A | (B + C) = (A | B) + (A | C) !(A + B) =! A |! B !(A | B) =! A +! B

A common mistake is to do something like this:

! A |! B |! C

This is false only if A, B and C are all simultaneously true (as it's the same as !(A + B + C)), and you may have possibly been after

! A +! B +! C

which is false if A is true, or B is true, or C is true.

One thing you will notice, is that when a control is hidden, it can't be focused. This means you can't move to a control and have it automatically become visible (eg even if it had Control.HasFocus(myID) it wouldn't come back on, as XBMC wouldn't allow navigation to the hidden control). To solve this issue, you can use: on a control of  21. This will allow the control to be focusable even when it's hidden. When the user moves to the hidden control, it will automatically unhide itself, due to the Control.HasFocus(21) visibility condition.

Specifying the Transition Animation
You can also specify how XBMC renders the transistion between the hidden and visible states (as well as between other states). See here for how to add animations to your skin.