It is currently April 25th, 2024, 4:23 am

Pages

Tips and Tricks from the Rainmeter Community
User avatar
Kaelri
Developer
Posts: 1721
Joined: July 25th, 2009, 4:47 am

Pages

Post by Kaelri »

Prompted by this thread, I wanted to provide a general method for displaying and manipulating "paged" elements in a skin.

Start by setting two variables: one for the currently-displayed "page," and another for the maximum number of pages that you'll be dealing with.

Code: Select all

[Variables]
CurrentPage=1
NumberOfPages=3
Next, create two Calc measures to calculate the numbers of the next and previous pages.

Code: Select all

[MeasureNextPage]
Measure=Calc
DynamicVariables=1
Formula=(#CurrentPage# % #NumberOfPages#) + 1
This formula divides the total number of pages by the current page, takes the remainder, and adds 1. Using the remainder makes sure that the pages "loop" back around when you reach the last page.

Code: Select all

[MeasurePreviousPage]
Measure=Calc
DynamicVariables=1
Formula=#CurrentPage# - 1 + (#CurrentPage# = 1 ? #NumberOfPages# : 0)
This formula takes the current page number, subtracts 1, and then, if you were already on page 1, adds the total number of pages in order to loop back to the last page. (Thanks to smurfier for simplifying my original formulas a bit.)

From here, there are a number of ways to change what the skin displays based on the current page number:

1) Meter Groups

This is the simplest method, and also the lightest in terms of system resources. All you have to do is assign each page's meters to a "group", and then use a !bang command to show and hide the appropriate groups.

Code: Select all

[MeterOnPage1]
Meter=...
Group=Page1

[MeterOnPage2]
Meter=...
Group=Page2

[MeterOnPage3]
Meter=...
Group=Page3

[ButtonSwitchToPreviousPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "[MeasurePreviousPage]"][!HideMeterGroup "Page#CurrentPage#"][!ShowMeterGroup "Page[MeasurePreviousPage]"]

[ButtonSwitchToNextPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "[MeasureNextPage]"][!HideMeterGroup "Page#CurrentPage#"][!ShowMeterGroup "Page[MeasureNextPage]"]
If you want to make the command a little "safer," you can also assign all pages to a common group, and send a !bang to hide all paged meters, regardless of which page is currently showing. This can be helpful, or at least reassuring, in large skins with lots of complex showing/hiding actions. It's also best if you want to have "tabs" to switch to specific pages:

Code: Select all

[MeterOnPage1]
Meter=...
Group=Page1 | AllPages

[MeterOnPage2]
Meter=...
Group=Page2 | AllPages

[MeterOnPage3]
Meter=...
Group=Page3 | AllPages

[ButtonSwitchToPage1]
Meter=...
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "1"][!HideMeterGroup "AllPages"][!ShowMeterGroup "Page1"]

[ButtonSwitchToPage2]
Meter=...
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "2"][!HideMeterGroup "AllPages"][!ShowMeterGroup "Page2"]

[ButtonSwitchToPage3]
Meter=...
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "3"][!HideMeterGroup "AllPages"][!ShowMeterGroup "Page3"]

[ButtonSwitchToNextPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "[MeasureNextPage]"][!HideMeterGroup "AllPages"][!ShowMeterGroup "Page[MeasureNextPage]"]

[ButtonSwitchToPreviousPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "[MeasurePreviousPage]"][!HideMeterGroup "AllPages"][!ShowMeterGroup "Page[MeasurePreviousPage]"]
Of course, if you only have a single meter for each page, you don't need to bother with groups at all.

Code: Select all

[ButtonSwitchToNextPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!Execute [!SetVariable CurrentPage "[MeasureNextPage]"][!HideMeter "MeterOnPage#CurrentPage#"][!ShowMeter "MeterOnPage[MeasureNextPage]"]
2) "Hide State" Measures

Since most of the time, the only difference between paged meters is whether they're visible or not, you can tell your meters to show or hide automatically, based on the current page number. Unfortunately, you can't use formulas in the "Hidden" key, so this requires a few extra measures. On the bright side, however, the page and "switch" meters are much easier to write. For small- to medium-sized skins, this is probably the ideal method.
Start by creating a new measure for each page, which returns true ("1") or false ("0") depending on whether the page is showing, and takes action accordingly.

Code: Select all

[MeasurePage1State]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#=1
IfEqualValue=1
IfEqualAction=!ShowMeterGroup "Page1"
IfBelowValue=1
IfBelowAction=!HideMeterGroup "Page1"

[MeasurePage2State]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#=2
IfEqualValue=1
IfEqualAction=!ShowMeterGroup "Page2"
IfBelowValue=1
IfBelowAction=!HideMeterGroup "Page2"

[MeasurePage3State]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#=3
IfEqualValue=1
IfEqualAction=!ShowMeterGroup "Page3"
IfBelowValue=1
IfBelowAction=!HideMeterGroup "Page3"
Next, assign each page's meters to the corresponding group, as before:

Code: Select all

[MeterOnPage1]
Meter=...
Group=Page1

[MeterOnPage2]
Meter=...
Group=Page2

[MeterOnPage3]
Meter=...
Group=Page3
And now, to switch pages, all you need to do is send a !bang command to change the #CurrentPage# variable:

Code: Select all

[ButtonSwitchToPage1]
Meter=...
LeftMouseUpAction=!SetVariable CurrentPage 1

[ButtonSwitchToPage2]
Meter=...
LeftMouseUpAction=!SetVariable CurrentPage 2

[ButtonSwitchToPage3]
Meter=...
LeftMouseUpAction=!SetVariable CurrentPage 3

[ButtonSwitchToNextPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!SetVariable CurrentPage [MeasureNextPage]

[ButtonSwitchToPreviousPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!SetVariable CurrentPage [MeasurePreviousPage]
By the same token, you can also tell the "next" and "previous" buttons to disappear on the last and first pages, respectively:

Code: Select all

[MeasurePage1State]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#=1
IfEqualValue=1
IfEqualAction=!Execute [!ShowMeterGroup "Page1"][!HideMeter "ButtonSwitchToPreviousPage"]
IfBelowValue=1
IfBelowAction=!Execute [!HideMeterGroup "Page1"][!ShowMeter "ButtonSwitchToPreviousPage"]

[MeasurePage3State]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#=3
IfEqualValue=1
IfEqualAction=!Execute [!ShowMeterGroup "Page3"][!HideMeter "ButtonSwitchToNextPage"]
IfBelowValue=1
IfBelowAction=!Execute [!HideMeterGroup "Page3"][!ShowMeter "ButtonSwitchToNextPage"]
3) Meter Styles

This is the most complex method, but also the most powerful. This is used when you don't want to simply hide meters based on the current page number, but to change other aspects of their appearance and behavior. For example, you might want your tab buttons to light up when the corresponding page is showing.
Start with measures similar to the ones from method #2:

Code: Select all

[MeasurePage1Hidden]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#<>1

[MeasurePage2Hidden]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#<>2

[MeasurePage3Hidden]
Measure=CALC
DynamicVariables=1
Formula=#CurrentPage#<>3
Then, assign each page's meters to use a corresponding "MeterStyle", much like you did to assign "Groups" in method #1:

Code: Select all

[MeterOnPage1]
Meter=...
DynamicVariables=1
MeterStyle=StylePage1

[MeterOnPage2]
Meter=...
DynamicVariables=1
MeterStyle=StylePage2

[MeterOnPage3]
Meter=...
DynamicVariables=1
MeterStyle=StylePage3
Then, define these styles:

Code: Select all

[StylePage1]
Hidden=[MeasurePage1Hidden]

[StylePage2]
Hidden=[MeasurePage3Hidden]

[StylePage3]
Hidden=[MeasurePage3Hidden]
Now, as is, this just gets you the same results as the last method, which isn't very helpful. However, we can use these styles to create additional options. For example, you could have each page show up in a different place:

Code: Select all

[StylePage1]
Hidden=[MeasurePage1Hidden]
X=0

[StylePage2]
Hidden=[MeasurePage3Hidden]
X=100

[StylePage3]
Hidden=[MeasurePage3Hidden]
X=200
You can also tell a meter to use different styles based on the page number. This is great for the example of changing tab buttons to "light up" only when their page is currently showing. You can tell the button meters to use options from either [StyleButton1] or [StyleButton0], based on the "Hide State" of the corresponding page:

Code: Select all

[ButtonSwitchToPage1]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!SetVariable CurrentPage 1
MeterStyle=StyleButton[MeasurePage1Hidden]

[ButtonSwitchToPage2]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!SetVariable CurrentPage 2
MeterStyle=StyleButton[MeasurePage2Hidden]

[ButtonSwitchToPage3]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!SetVariable CurrentPage 3
MeterStyle=StyleButton[MeasurePage3Hidden]
Now we can set different options on the buttons for each case. For example, set the tab images for inactive pages as partially transparent:

Code: Select all

[StyleButton0]
ImageAlpha=255

[StyleButton1]
ImageAlpha=128
4) @include

The last option is for very large skins, with a great deal of content on each page. With this method, your skin file serves only as a shell, or frame, and draws the page content from separate ".inc" files. This allows you to load only the resources that you need, instead of taking up memory with measures and meters that aren't even visible. The downside is that the skin must be refreshed when switching pages, so any cumulative measure values or dynamic variables will be reset, and WebParser measures will be forced to reconnect.
In terms of actual code, this is actually the simplest of all the methods:

Code: Select all

@include=Page#CurrentPage#.inc
And that's it. All you have to do is create separate files in the skin folder, called "Page1.inc", "Page2.inc", etc. Then just cut-and-paste all of your paged meters into those files.

As for your switch meters, make sure to change their !bang commands from "!SetVariable" to "!WriteKeyValue." For this to work, the new page number needs to be actually written to the file.

Code: Select all

[ButtonSwitchToPage1]
Meter=...
LeftMouseUpAction=!Execute[!WriteKeyValue "Variables" "CurrentPage" "1"][!Refresh]

[ButtonSwitchToPage2]
Meter=...
LeftMouseUpAction=!Execute[!WriteKeyValue "Variables" "CurrentPage" "2"][!Refresh]

[ButtonSwitchToPage3]
Meter=...
LeftMouseUpAction=!Execute[!WriteKeyValue "Variables" "CurrentPage" "3"][!Refresh]

[ButtonSwitchToNextPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!Execute[!WriteKeyValue "Variables" "CurrentPage" "[MeasureNextPage]"][!Refresh]

[ButtonSwitchToPreviousPage]
Meter=...
DynamicVariables=1
LeftMouseUpAction=!Execute[!WriteKeyValue "Variables" "CurrentPage" "[MeasurePreviousPage]"][!Refresh]
You can also choose to remove "DynamicVariables=1" from your original [MeasureNextPage] and [MeasurePreviousPage] measures, since the value of #CurrentPage# will not be changing dynamically anymore.
These are just a few ways of getting this job done. I can think of about fifty more things you could do with it - particularly with the Styles method - but this post has already grown much longer than I expected. Feel free to post your own variations below. :)
User avatar
smurfier
Moderator
Posts: 1931
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: Pages

Post by smurfier »

I believe the method you used in the Enigma Options panel deserves a spot here as it's quite ingenious and cuts down on lengthy skin codes.
GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
Kaelri
Developer
Posts: 1721
Joined: July 25th, 2009, 4:47 am

Re: Pages

Post by Kaelri »

smurfier wrote:I believe the method you used in the Enigma Options panel deserves a spot here as it's quite ingenious and cuts down on lengthy skin codes.
Thankye. :) I'll add that at the end. Probably most appropriate for skins with an extremely large numbers of meters on each page (for which Options certainly qualifies).