It is currently March 28th, 2024, 8:58 pm

LoadSkin 3.0.0

Skins that control functions in Windows or Rainmeter
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

LoadSkin 3.0.0

Post by raiguard »

loadskin.gif
LoadSkin is a LUA script that I created to ease the creation of skin load/unload buttons. All you need to supply is the config name, and optionally the name of the INI you wish to toggle, and the script will handle detecting which skin is active, and all of the logic necessary to toggle it. You can also specifically load/unload a skin, and in this case, the script prevents warning or error messages from filling the log when activating an already activated skin, and vice versa.

The skin is very simple to use, and it quite easy to figure out just by looking at the example skin, but just in case one wants a more in-depth explanation, I have thoroughly documented everything in the script's code.

There is only one downside to this script: Because of a flaw in how !CommandMeasure works, you must use double backslashes (\\) in all of your config names. There is no timeline for when this issue will be fixed, if ever, so this is a semi-permanent workaround. Sorry!

(And before anyone comments about this, I know you can use inline LUA in place of a !CommandMeasure bang to avoid this problem, but I have had Rainmeter randomly hard-crash for no apparent reason when doing that, so I prefer to use !CommandMeasure bangs...)

The included example skin demonstrates some of the capabilities of the script in various usecases. It is meant to be as easy as possible to learn from and copy, so things are a bit oversimplified.

Here is the script code:

Code: Select all

--[[
--------------------------------------------------

LOADSKIN.LUA
raiguard
v3.0.0

--------------------------------------------------

Release Notes:
v3.0.0 - 2018-10-28
- Redesigned script to simplify the required inputs
- Improved documentation
v2.0.0 - 2018-6-22
- Updated to use the new ConfigActive plugin rather than WebParser
v1.3.0 - 2018-6-21
- The script now gets the input from a WebParser measure, rather than directly parsing
  Rainmeter.ini (for Rainmeter 4.2+ compatibility)
v1.2.0 - 2017-12-27
 - Added ability to specifically load or unload skins, rather than always toggling them
v1.1.0 - 2017-12-7
 - Consolidated LoadConfig() into LoadSkin()
v1.0.0 - 2017-10-2
 - Initial release

--------------------------------------------------

This script loads / unlaods the specified skin or config, and sets parameters for toggle
buttons related to those skins.


INSTRUCTIONS FOR USE:
Copy this file and paste it into your own suite. First, you will need to create a
ConfigActive plugin measure:

	[MeasureConfigActive]
	Measure=Plugin
	Plugin=ConfigActive

That's all you need to add to this measure, the script will handle the rest. Speaking of
the script, that is the next measure you need to create:

	[MeasureLoadSkinScript]
	Measure=Script
	ScriptFile=#@#Scripts\LoadSkin.lua
	ToggleOn=#@#Images\toggle-on.png
	ToggleOff=#@#Images\toggle-off.png
	ToggleGroup=ToggleButtons
	MeasureName=MeasureConfigActive

The 'ToggleOn' and 'ToggleOff' parameters are for the toggle buttons. If you are using
images, these will be the image paths for the buttons' respective on and off states. If
you are using strings, these will be the 'on' and 'off' strings that will show on the
buttons. If you do not include these parameters, the script will default to 'Enabled'
and 'Disabled' respectively.

There are also optional 'RadioOn' and 'RadioOff' options for the script measure. This
allows you to specify a different set of images or strings for 'radio buttons', usually
to have buttons that will load different variants of a config. These options are
optional, and if left unspecified, will be defined as what you set in 'ToggleOn' and
'ToggleOff' respectively.

The 'ToggleGroup' parameter specifies the group that the toggle button meters belong to.
If you do not include this option, it will default to 'SkinToggles'.

Last but not least, the 'MeasureName' option is simply the name of the ConfigActive
measure that you created before. If unspecified, it will default to 'MeasureConfigActive'.

A toggle button meter should look something like this:

	[MeterToggleSystem]
	Meter=Image
	ImageName=[&MeasureLoadSkinScript:GetIcon('illustro\\System')]
	X=5
	Y=5
	W=31
	H=20
	LeftMouseUpAction=[!CommandMeasure MeasureLoadSkinScript "ToggleSkin('illustro\\System')"]
	DynamicVariables=1
	Group=SkinToggles

The toggle buttons get their parameters via inline LUA, which requires that
'DynamicVariables=1' must be set on all the buttons. The buttons must also belong to the
group specified in the script measure.

Obviously, if you are using strings as your buttons, the inline LUA will be contained in
the 'Text' option, rather than 'ImageName'.

--------------------------------------------------
]]--

function Initialize()

	toggleOn = SELF:GetOption('ToggleOn', 'Enabled')
	toggleOff = SELF:GetOption('ToggleOff', 'Disabled')
	radioOn = SELF:GetOption('RadioOn', toggleOn)
	radioOff = SELF:GetOption('RadioOff', toggleOff)
	toggleGroup = SELF:GetOption('ToggleGroup', 'SkinToggles')
	caMeasureName = SELF:GetOption('MeasureName', 'MeasureConfigActive')
	measureCA = SKIN:GetMeasure(caMeasureName)

end

function Update() end

-- toggles or sets the specified skin or config
function ToggleSkin(configName, iniName, toState)

	--[[
		PLEASE NOTE THAT THE DOUBLE BACKSLASHES ARE ALWAYS REQUIRED BECAUSE OF LUA SHENANIGANS
		configName: the name of the config you wish to toggle (e.g. 'illustro\\Disk')
		iniName (optional): the name of the skin INI you wish to toggle (e.g. '1 Disk.ini')
		toState (optional): the state you wish to set the skin to (1 for active, -1 for inactive)
	]]--

	local configState, activeIni = GetConfigState(configName)
	local toState = toState or iniName and (iniName == activeIni and -1 or 1) or configState * -1

	if toState == 1 then
		if iniName == nil then
			SKIN:Bang('!ActivateConfig', configName)
		elseif iniName ~= activeIni then
			SKIN:Bang('!ActivateConfig', configName, iniName)
		end
	elseif configState == 1 then
		SKIN:Bang('!DeactivateConfig', configName)
	end

	SKIN:Bang('!UpdateMeterGroup', toggleGroup)
	SKIN:Bang('!Redraw')

end

-- returns the corresponding button state
function GetIcon(configName, iniName, radio)

	--[[
		PLEASE NOTE THAT THE DOUBLE BACKSLASHES ARE ALWAYS REQUIRED BECAUSE OF LUA SHENANIGANS
		configName: the name of the relevant config (e.g. 'illustro\\Disk')
		iniName (optional): the name of the relevant INI file (e.g. '1 Disk.ini')
		radio: if set to true, the function will return the 'radioOn' and 'radioOff' options,
			   instead of 'toggleOn' and 'toggleOff'
	]]--
	
	local configState, activeIni = GetConfigState(configName)
	-- determine which icon to provide
	if iniName then
		if configState == 1 and activeIni == iniName then return radio and radioOn or toggleOn
		else return radio and radioOff or toggleOff end
	else
		if configState == 1 then return radio and radioOn or toggleOn
		else return radio and radioOff or toggleOff end
	end

end

-- retrieves config state and active INI
function GetConfigState(configName)

	SKIN:Bang('!SetOption', caMeasureName, 'ConfigName', configName)
	SKIN:Bang('!UpdateMeasure', caMeasureName)
	return measureCA:GetValue(),	   -- active state of the config (1 or -1)
		   measureCA:GetStringValue()  -- name of the currently active INI (if inactive, returns -1)

end
And, of course, the example skin INI:

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Metadata]
Name=LoadSkin
Author=raiguard
Information=Demonstrates the capabilities of the LoadSkin.lua script.
Version=3.0.0
License=Creative Commons Attribution - Non - Commercial - Share Alike 3.0

[Variables]

[StyleStringButton]
FontFace=Roboto
FontColor=240,240,240
FontSize=10
AntiAlias=1
X=6
Y=4R
MouseOverAction=[!SetOption #CURRENTSECTION# FontColor "200,50,50"][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseLeaveAction=[!SetOption #CURRENTSECTION# FontColor ""][!UpdateMeter #CURRENTSECTION#][!Redraw]

[StyleStringLabel]
FontFace=Roboto
FontColor=240,240,240
FontSize=10
AntiAlias=1
X=3R
Y=-1r

[StyleToggleButton]
FontFace=ElegantIcons
FontColor=137,190,250
FontSize=12
AntiAlias=1
X=6
Y=4R
Group=SkinToggles
DynamicVariables=1
MouseOverAction=[!SetOption #CURRENTSECTION# FontColor "200,50,50"][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseLeaveAction=[!SetOption #CURRENTSECTION# FontColor ""][!UpdateMeter #CURRENTSECTION#][!Redraw]

; ==================================================
; MEASURES
; ==================================================

[MeasureConfigActive]
Measure=Plugin
Plugin=ConfigActive

[MeasureScript]
Measure=Script
ScriptFile=#@#Scripts\LoadSkin.lua
ToggleOn=[\x5a]
ToggleOff=[\x56]
RadioOn=[\x5c]
RadioOff=[\x5b]
ToggleGroup=SkinToggles
MeasureName=MeasureConfigActive

; ==================================================
; METERS
; ==================================================

[MeterBackground]
Meter=Shape
Shape=Rectangle 1,1,173,120,3 | Fill Color 15,15,15 | Stroke Color 50,50,50 | StrokeWidth 2

[MeterToggleSystemButton]
Meter=String
MeterStyle=StyleToggleButton
Y=6
Text=[&MeasureScript:GetIcon('illustro\\System')]
LeftMouseUpAction=[!CommandMeasure MeasureScript "ToggleSkin('illustro\\System')"]

[MeterToggleSystemButtonLabel]
Meter=String
MeterStyle=StyleStringLabel
Text=Toggle 'illustro\System'

[MeterToggleDiskButton]
Meter=String
MeterStyle=StyleToggleButton
Text=[&MeasureScript:GetIcon('illustro\\Disk')]
LeftMouseUpAction=[!CommandMeasure MeasureScript "ToggleSkin('illustro\\Disk')"]

[MeterToggleDiskButtonLabel]
Meter=String
MeterStyle=StyleStringLabel
Text=Toggle 'illustro\Disk'

[MeterLoad1DiskButton]
Meter=String
MeterStyle=StyleToggleButton
X=23
Text=[&MeasureScript:GetIcon('illustro\\Disk', '1 Disk.ini', true)]
LeftMouseUpAction=[!CommandMeasure MeasureScript "ToggleSkin('illustro\\Disk', '1 Disk.ini', 1)"]

[MeterLoad1DiskButtonLabel]
Meter=String
MeterStyle=StyleStringLabel
Text=Load '1 Disk.ini'

[MeterLoad2DiskButton]
Meter=String
MeterStyle=StyleToggleButton
X=23
Text=[&MeasureScript:GetIcon('illustro\\Disk', '2 Disks.ini', true)]
LeftMouseUpAction=[!CommandMeasure MeasureScript "ToggleSkin('illustro\\Disk', '2 Disks.ini', 1)"]

[MeterLoad2DiskButtonLabel]
Meter=String
MeterStyle=StyleStringLabel
Text=Load '2 Disks.ini'

[MeterLoadClockButton]
Meter=String
MeterStyle=StyleStringButton
Text=Load 'illustro\Clock'
LeftMouseUpAction=[!CommandMeasure MeasureScript "ToggleSkin('illustro\\Clock', nil, 1)"]

[MeterUnloadClockButton]
Meter=String
MeterStyle=StyleStringButton
Text=Unload 'illustro\Clock'
LeftMouseUpAction=[!CommandMeasure MeasureScript "ToggleSkin('illustro\\Clock', nil, -1)"]
You do not have the required permissions to view the files attached to this post.
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
sl23
Posts: 1140
Joined: February 17th, 2011, 7:45 pm
Location: a Galaxy S7 far far away

Re: LoadSkin 3.0.0

Post by sl23 »

I just created a simple skin selector and was wondering how to make the buttons toggle there highlighted state.

Is that achievable without lua?
- MuLab -
User avatar
SilverAzide
Rainmeter Sage
Posts: 2588
Joined: March 23rd, 2015, 5:26 pm

Re: LoadSkin 3.0.0

Post by SilverAzide »

sl23 wrote: September 11th, 2021, 2:34 pm I just created a simple skin selector and was wondering how to make the buttons toggle there highlighted state.

Is that achievable without lua?
Yes, it can be done without Lua, but it is a LOT more work. I don't want to speak for raiguard here, but the best use of this LoadSkin script, besides the toggling of the checkboxes/radio buttons, was in an older version of the script/skin. It used to be very difficult to determine if a skin was loaded or not; you actually had to read Rainmeter.ini using a Lua script to determine if any particular skin was active. But since JSMorley's ConfigActive plugin was released, all that nightmarish Lua and parsing was completely eliminated. So LoadSkin 3.0 now is mostly useful for learning a way to toggle controls programmatically instead of using tons of Rainmeter code.

If you want to see a non-Lua variant for how to toggle a button's state, in the Gadgets suite, check out the Welcome skin. I'm sure there are even better examples out there, but this is one way to do it.
Gadgets Wiki GitHub More Gadgets...
User avatar
sl23
Posts: 1140
Joined: February 17th, 2011, 7:45 pm
Location: a Galaxy S7 far far away

Re: LoadSkin 3.0.0

Post by sl23 »

Ok thank you I'll take a look :thumbup:
- MuLab -
User avatar
Kurou
Posts: 40
Joined: January 24th, 2022, 2:54 pm
Location: World Wide Web

Re: LoadSkin 3.0.0

Post by Kurou »

raiguard wrote: October 28th, 2018, 5:59 am
loadskin.gif
LoadSkin is a LUA script that I created to ease the creation of skin load/unload buttons. All you need to supply is the config name, and optionally the name of the INI you wish to toggle, and the script will handle detecting which skin is active, and all of the logic necessary to toggle it. You can also specifically load/unload a skin, and in this case, the script prevents warning or error messages from filling the log when activating an already activated skin, and vice versa.
Wouldn't this be much simplier way?

Rainmeter Measures Code:

Code: Select all

[Script]
Measure=Script
ScriptFile=#@#\lua\control.lua

[Measure_ConfigActive]
Measure=Plugin
Plugin=ConfigActive
Lua Code:

Code: Select all

--  ToolTip
function ToolTip(text, hover, meter, folder, skin)
    if hover == "true" then
        ConfigActive_Toggle(folder, skin, '-1')
        SKIN:Bang("!SetOption", meter, "Text", text, folder, skin)
        SKIN:Bang("!Redraw", folder, skin)
    elseif hover == "false" then
        ConfigActive_Toggle(folder, skin, '1')
    end
end

-- ConfigActive handler
function ConfigActive_Toggle(folder, skin, state)
	local current_state = ConfigActive_State('Measure_ConfigActive', folder, skin)

    if current_state ~= state then
        if state == "1" then
            SKIN:Bang("!DeactivateConfig", folder, skin)
        elseif state == "-1" then
            SKIN:Bang("!ActivateConfig", folder, skin)
        end
    else
        print("Lua Error | ConfigActive_Toggle("..folder..") Cannot change state to the same value!")
    end
end

function ConfigActive_State(MeasureName, skin_folder, skin)
    --  Obtain measure
	MeasureName_Value = SKIN:GetMeasure(MeasureName)

    --  Update measure
	SKIN:Bang('!SetOption', MeasureName, 'ConfigName', skin_folder)
	SKIN:Bang('!UpdateMeasure', MeasureName)
	return  MeasureName_Value:GetValue(), MeasureName_Value:GetStringValue()
end
Hovering on the meter, activates skin config and changes text of the meter inside that config. When mouse leaves meter, configs is deactivated.

Example:

Code: Select all

[Simple_meter]
Meter=Image
SolidColor=255,255,255
W=50
H=50
X=0
Y=0
MouseOverAction=[!CommandMeasure "Script" "ToolTip('Text to display!', 'true', 'ToolTip_Text', '#ROOTCONFIG#\\control\\tooltip', 'tooltip.ini')"]
MouseLeaveAction=[!CommandMeasure "Script" "ToolTip('This wont be shown', 'false', 'ToolTip_Text', '#ROOTCONFIG#\\control\\tooltip', 'tooltip.ini')"]
example.gif
You do not have the required permissions to view the files attached to this post.
Brought to you by: https://kurou.dev/
User avatar
SilverAzide
Rainmeter Sage
Posts: 2588
Joined: March 23rd, 2015, 5:26 pm

Re: LoadSkin 3.0.0

Post by SilverAzide »

Kurou wrote: May 28th, 2023, 6:03 pm Wouldn't this be much simplier way?
No, not in 2017 when that script was first written. The ConfigActive plugin didn't exist at that time. Before ConfigActive, the only way to tell if a skin was loaded or not was by reading Rainmeter.ini with a Lua script (or WebParser). Later versions of the LoadSkin script were updated to use ConfigActive, so the most useful purpose of the script now is to show how to toggle checkboxes and option buttons programmatically.
Gadgets Wiki GitHub More Gadgets...
User avatar
Kurou
Posts: 40
Joined: January 24th, 2022, 2:54 pm
Location: World Wide Web

Re: LoadSkin 3.0.0

Post by Kurou »

SilverAzide wrote: May 28th, 2023, 11:43 pm No, not in 2017 when that script was first written. The ConfigActive plugin didn't exist at that time. Before ConfigActive, the only way to tell if a skin was loaded or not was by reading Rainmeter.ini with a Lua script (or WebParser). Later versions of the LoadSkin script were updated to use ConfigActive, so the most useful purpose of the script now is to show how to toggle checkboxes and option buttons programmatically.
:sly:
Brought to you by: https://kurou.dev/