It is currently September 26th, 2022, 8:56 am

Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Get help with creating, editing & fixing problems with skins
MattNY177
Posts: 28
Joined: December 3rd, 2018, 1:15 am

Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by MattNY177 »

Hello,

I'm working on a skin that has lots of numbered meter groups:
  • Each group has a container (box1, box2, ... , box100) with components that are named so they can be derived from the #CURRENTSECTION# variable of its container (box1_text, box1_icon, etc).
  • Each component meter name is also used as a variable to store user defined inputs.
  • When the user interacts with a container "box", it writes the #CURRENTSECTION# key value to the #ACTIVEBOX# variable which can then be used to reference other related measures/meters (#ACTIVEBOX#_text, #ACTIVEBOX#_icon, etc)
I have already set up a system for the user to add/edit/delete values for all the boxes, which are displayed in numerical order. What I am trying to do is allow the user to "insert" a blank box in the middle of other boxes, which would essentially just copy/paste all variables from their current box and higher to the next numbered box, and the last box would be overwritten.

For example: user wants to insert blank box in slot 75. The contents of all box99_***** variables would be copied to box100, and so on until box75 gets copied to box76 leaving box75 blank.

I have tried using several combinations of ActionTimer/Calc measures, nested variables with both !WriteKeyValue and !SetVariable, starting at 100 and counting down (with clamp) to the current box, adding !Update at the end of each cycle, but for some reason I cannot seem to get it working.

Rather than share my admittedly sloppy attempts, I am curious how a more experienced developer would attempt to achieve this in their own skin so that I may try adapting it to work with my version?
User avatar
Active Colors
Moderator
Posts: 1182
Joined: February 16th, 2012, 3:32 am
Location: Berlin, Germany

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by Active Colors »

Hi there,
At the moment I don't have time digging through your task, however, this reminds me of my questions I asked sometime ago.
Check this thread:
https://forum.rainmeter.net/viewtopic.php?p=204537#p204537
To be specific, it is similar that I also needed to run repeated actions which involved the same meters and incremented section names numbers.
I think that some of the proposed solutions in the tread might fit you.
MattNY177
Posts: 28
Joined: December 3rd, 2018, 1:15 am

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by MattNY177 »

Active Colors wrote: July 26th, 2022, 7:53 am Hi there,
At the moment I don't have time digging through your task, however, this reminds me of my questions I asked sometime ago.
Check this thread:
https://forum.rainmeter.net/viewtopic.php?p=204537#p204537
To be specific, it is similar that I also needed to run repeated actions which involved the same meters and incremented section names numbers.
I think that some of the proposed solutions in the tread might fit you.
Hey, thanks for the info! I checked that thread and it does have some useful information, seems like a good place to start.

There's one big difference though... what you were doing could be calculated in a single iteration, whereas what I'm trying to do would require multiple iterations/loops each time the count variable is updated. To provide some additional simplified context...

Code: Select all

[Variables]
ACTIVEBOX = box75 <-- [!WriteKeyValue variables ACTIVEBOX #CURRENTSECTION#]
ACTIVENUM = 75 <-- [!WriteKeyValue variables ACTIVENUM [&[#CURRENTSECTION]_num]]
; box75_num is a calc measure to obtain the raw integer
COPYFROM = 99 <-- Reset at beginning of loop
COPYTO = 100 <-- Reset at beginning of loop
Loop #1 should achieve the following...
  • #box99_text# --> #box100_text#
    (using #COPYFROM# in nested variable: [#box[#COPYFROM]_text] --> [#box[#COPYTO]_text])
  • #box99_icon# --> #box100_icon#
    (using #COPYTO# in nested variable: [#box[#COPYFROM]_icon] --> [#box[#COPYTO]_icon])
  • ... repeat for all box99_ prefix variables
At the end of each loop, COPYFROM and COPYTO are reduced by 1, then the loop should repeat copying box98 to box99, and so on. The loop should end when #ACTIVENUM# = #COPYFROM#, and after the final loop is completed, the active box variables should all be set to empty.

I have tried doing this using ActionTimer and Loop measures, but I'm having trouble getting the formulas to reference the correct numbers/boxes after each update cycle, so I think I just don't understand how to combine a repeating update loop with changing variables using the !WriteKeyValue function.
User avatar
CodeCode
Posts: 1084
Joined: September 7th, 2020, 2:24 pm
Location: QLD, Australia

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by CodeCode »

Ok. If you would like the ability to insert a new BOX somewhere in the list of existing boxes. You might try also creating an 'invisible' box that holds the box 99 info in it. So when you are cycling (not looping technically), the final box will still be there until the new box is decked out with the info parts that become available. Sort of a buffer - in concept anyway.

Another idea is similar but different. Create two new boxes, one to keep and the other to store temporary info in, then is discarded.

Jus ideas. Cant really duplicate your code, but you seem to have a strong grasp to start with.

Good Luck. :great:
ƈǟռ'ȶ ʄɨӼ ɨȶ ɨʄ ɨȶ ǟɨռ'ȶ ɮʀօӄɛ - ʊռʟɛֆֆ ɨȶ ɨֆ ɨռ ƈօɖɛ.
User avatar
balala
Rainmeter Sage
Posts: 14552
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by balala »

MattNY177 wrote: July 26th, 2022, 5:43 am I'm working on a skin that has lots of numbered meter groups:
  • Each group has a container (box1, box2, ... , box100) with components that are named so they can be derived from the #CURRENTSECTION# variable of its container (box1_text, box1_icon, etc).
  • Each component meter name is also used as a variable to store user defined inputs.
  • When the user interacts with a container "box", it writes the #CURRENTSECTION# key value to the #ACTIVEBOX# variable which can then be used to reference other related measures/meters (#ACTIVEBOX#_text, #ACTIVEBOX#_icon, etc)
I have already set up a system for the user to add/edit/delete values for all the boxes, which are displayed in numerical order. What I am trying to do is allow the user to "insert" a blank box in the middle of other boxes, which would essentially just copy/paste all variables from their current box and higher to the next numbered box, and the last box would be overwritten.

For example: user wants to insert blank box in slot 75. The contents of all box99_***** variables would be copied to box100, and so on until box75 gets copied to box76 leaving box75 blank.

I have tried using several combinations of ActionTimer/Calc measures, nested variables with both !WriteKeyValue and !SetVariable, starting at 100 and counting down (with clamp) to the current box, adding !Update at the end of each cycle, but for some reason I cannot seem to get it working.
A sample code would be nice, because it is extremely hard to say something meaningful if we don't have something to work with. So, please post one...
MattNY177
Posts: 28
Joined: December 3rd, 2018, 1:15 am

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by MattNY177 »

balala wrote: July 26th, 2022, 7:07 pm A sample code would be nice, because it is extremely hard to say something meaningful if we don't have something to work with. So, please post one...
I've stripped out most of the styles/attributes and unrelated sections to focus on the relevant functions.

From the skin that displays the boxes (boxes.ini):

Code: Select all

[box1_number]
 Measure=Calc
 Formula=1
[box1_container]
 Meter=Image
[box1_icon]
 Meter=Image
 Container=box1_container
[box1_text]
 Meter=String
 Container=box1_container
[box1]
 Meter=Image
 MeterStyle=styleBox
 Container=box1_container

; ... repeat thru 100

[styleBox]
 DynamicVariables=1
 LeftMouseUpAction=[!WriteKeyValue variables active [&[#CURRENTSECTION]_number] #@#vars.inc][!Update][!ActivateConfig "boxes/editBox" "editBox.ini"]
From the shared #@#vars.inc file:

Code: Select all

[variables]

 active=
 copyFrom=
 copyTo=
 loopCount=

 ;user defined inputs
 box1_icon="C:\pictures\icons\chrome.png"
 box1_text="Google Chrome"
 ; ... repeat thru 100
From the skin that lets the user edit the boxes (editBox.ini):

Code: Select all

;Button to initiate the process
[InsertBox]
 Meter=String
 Text=Insert New Box
 LeftMouseDownAction=[!WriteKeyValue variables copyFrom "99" #@#vars.inc][!WriteKeyValue variables copyTo "100" #@#vars.inc][!WriteKeyValue variables loopCount "(#copyFrom# - #active#)" #@#vars.inc][!Update][!CommandMeasure measure_InsertBox "Execute 1"]

[measure_InsertBox]
 Measure=Plugin
 Plugin=ActionTimer
 ActionList1=FirstCopy|Wait 100|Repeat CopyBoxes,100,#loopCount#
 FirstCopy=[!UpdateMeasure measure_CopyBox]
 CopyBoxes=[!SetVariable copyFrom "(Clamp(#copyFrom#-1,#active#,99))"][!SetVariable copyTo "(Clamp(#copyTo#-1,#active#,100))"][!UpdateMeasure measure_CopyBox]

[measure_CopyBox]
 Measure=Calc
 Formula=#copyFrom#
 DynamicVariables=1
 IfCondition=([measure_CopyBox] > #active#)
 IfTrueAction=[!WriteKeyValue variables [#box[#copyTo]_icon] """"[#box[#copyFrom]_icon]"""" #@#vars.inc][!WriteKeyValue variables [#box[#copyTo]_text] """"[#box[#copyFrom]_text]"""" #@#vars.inc][!Update]
 IfFalseAction=[!WriteKeyValue variables [#box[#active]_icon] "" #@#vars.inc][!WriteKeyValue variables [#box[#active]_text] "" #@#vars.inc][!CommandMeasure measure_InsertBox "Stop 1"][!Refresh]
This is one of several attempts, I've also tried something similar using the loop measure, changing IfConditions, etc. The thing I am most unsure of is how to properly utilize !Update and !WriteKeyValue when cycling through these loops.
User avatar
balala
Rainmeter Sage
Posts: 14552
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by balala »

MattNY177 wrote: July 27th, 2022, 2:04 am This is one of several attempts,
Even if a little bit late, here is my attempt. Note that this code does work only with the boxXX_text variable, for tryout. If this is properly working, the other variables can and have to be added with !SetVariable and !WriteKeyValue bangs to the OnChangeAction and IfTrueAction options of the [MeasureProcessing] measure.
So replace the code of the editBox.ini skin with the following one:

Code: Select all

[Variables]
@Include=#@#Vars.inc
Wait=100

;Button to initiate the process
[InsertBox]
Meter=String
Text=Insert New Box
SolidColor=0,0,0,1
LeftMouseUpAction=[!SetVariable Processing "102"][!UpdateMeasure "MeasureCopy"][!CommandMeasure "MeasureCopy" "Execute 1"]

[MeasureCopy]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat Copy,#Wait#,100 | Wait 20 | DisableMeas
Copy=[!SetVariable Processing "(Clamp((#Processing#-1),(#active#+1),101))"][!EnableMeasure "MeasureProcessing"][!UpdateMeasure "MeasureCopy"][!UpdateMeasure "MeasureCopyFrom"][!UpdateMeasure "MeasureProcessing"]
DisableMeas=[!DisableMeasure "MeasureProcessing"]
DynamicVariables=1

[MeasureCopyFrom]
Measure=Calc
Formula=( #Processing# - 1 )
DynamicVariables=1

[MeasureProcessing]
Measure=Calc
Formula=#Processing#
OnChangeAction=[!SetVariable box[#Processing]_text "[#box[&MeasureCopyFrom]_text]"][!WriteKeyValue Variables box[#Processing]_text "[#box[&MeasureCopyFrom]_text]" "#@#vars.inc"]
IfCondition=(#CURRENTSECTION#=#active#+1)
IfTrueAction=[!Delay "#Wait#"][!SetVariable box[&MeasureCopyFrom]_text ""][!WriteKeyValue Variables box[&MeasureCopyFrom]_text "" "#@#vars.inc"]
DynamicVariables=1
Disabled=1
A few more thing related to this code:
  • I added a variable called Wait. This is the waiting time of processing consecutive variables (in milliseconds). The lower value you set for this variable, the quicker the processing goes on.
  • I added a SolidColor=0,0,0,1 option to the [InsertBox] meter, to get it easier clickable. This creates a not-visible background around the text, which reacts to mouse clicking.
Please check the above code and let me know how is it working.
MattNY177
Posts: 28
Joined: December 3rd, 2018, 1:15 am

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by MattNY177 »

balala wrote: July 28th, 2022, 9:17 am Please check the above code and let me know how is it working.
Thanks! So far the basic version seems to work well, gonna add the rest of the variables and do some more testing now.

The only other thing I'm trying to add is some visual indication when the job is done. I tried adding this code to the end of the IfTrueAction of MeasureProcessing but it doesn't take effect until after I mouse over another object:

Code: Select all

[!SetOption InsertBox Text "Done!"][!Update][!Redraw]
Is there a better place to put this so it happens right away?
User avatar
balala
Rainmeter Sage
Posts: 14552
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by balala »

MattNY177 wrote: July 29th, 2022, 2:04 am Thanks! So far the basic version seems to work well, gonna add the rest of the variables and do some more testing now.
Great! Please feel free to come back if you don't succeed.
MattNY177 wrote: July 29th, 2022, 2:04 am The only other thing I'm trying to add is some visual indication when the job is done. I tried adding this code to the end of the IfTrueAction of MeasureProcessing but it doesn't take effect until after I mouse over another object:

Code: Select all

[!SetOption InsertBox Text "Done!"][!Update][!Redraw]
Is there a better place to put this so it happens right away?
No, there is not. Adding the bangs to the IfTrueAction option of the [MeasureProcessing] measure is perfectly alright and does the job. One single observation I have, namely that it's completely useless to use the [!Update] and [!Redraw] bangs altogether, because when you update the skin (and doesn't really matter if the update is done "normally" - the update controlled by the Update option of the [Rainmeter] section - or through a [!Update] bang), a redrawn is also done, so doesn't worth to add a [!Redraw] bang altogether with a [!Update]. But you don't really have to update the whole skin, updating only the appropriate meter (in this case [InsertBox]) is completely enough. So the mentioned IfTrueAction option should look like this: IfTrueAction=[!Delay "#Wait#"][!SetVariable box[&MeasureCopyFrom]_text ""][!WriteKeyValue Variables box[&MeasureCopyFrom]_text "" "#@#vars.inc"][!SetOption InsertBox Text "Done!"][!UpdateMeter "InsertBox"][!Redraw]. This does work for me, it should for you as well. Please check. Does it?
MattNY177
Posts: 28
Joined: December 3rd, 2018, 1:15 am

Re: Need help using ActionTimer, Loop and/or Calc measures to edit multiple variables

Post by MattNY177 »

balala wrote: July 29th, 2022, 4:34 pm This does work for me, it should for you as well. Please check. Does it?
Thanks again, I guess it had something to do with !Update vs !Update meter. Do you have a tip jar or something? Lol.

Since it seems to be working now, to better understand how Rainmeter works "under the hood" I'm curious what was wrong with the original version I posted? Specifically:
  • Did it have anything to do with using !SetVariable after !WriteKeyValue? Does the order of these commands matter when applying to the same variable?
  • Was using OnChangeAction the only way to achieve this result? Why couldn't the same thing be achieved with IfConditions after updating the Calc measure during each cycle of the ActionTimer measure?
  • Could this also have been done using a Loop measure? In theory that seems like the most applicable tool for this scenario, versus a calc measure with Formula=#variable#-1
Again I'm just trying to learn these little nuances, so I appreciate any insight to help me increase my proficiency.