It is currently May 1st, 2024, 4:15 pm

Possible to expand/contract skin width from right edge instead of left? (Align)

Get help with creating, editing & fixing problems with skins
Crest
Posts: 115
Joined: August 16th, 2013, 12:47 pm

Possible to expand/contract skin width from right edge instead of left? (Align)

Post by Crest »

The goal is to have a skin with a dynamic string that expands outward from the right edge of the skin. So when the string becomes wider/narrower the skin width visually changes from the existing right edge instead of from the left outward like it does by default.

Explained visually in this image:
Concept.png
(Example for demonstration purposes but the skin graphics could be anything)



My current thinking was shifting the X coordinates of the skin via an OnUpdateAction on the Time measure with a SetWindowPosition bang and AnchorX value (positive AnchorX values move the skin to the left, so I'd have to determine the offset via some separate calc).

The only way I can think of determining this offset would be somehow storing the width of the string from the prior change (in this case the prior time) then comparing that width with the current string width (current time) to see if there's a width change then making the difference the AnchorX value for that update cycle.

Is there a more straightforward way? I'm not sure how I'd store the prior time width value besides writing the values to a file then using a WebParser to check the prior value, but I'd much prefer not to have to write to a file every minute just for this.



Spoilered below is a simplified test case skin based on the example image. The TimeMeasure Format values can be toggled between by uncommenting the different lines which affects the SkinWidth measure being used to calculate the background shape.

Code: Select all

[Rainmeter]
AccurateText=1
DynamicWindowSize=1
Update=1000

[Variables]
Pad=15

[SkinWidth]
Measure=Calc
Formula=[TimeString:W] + (#Pad# * 2)
DynamicVariables=1

[TimeMeasure]
Measure=Time
; Format=%I:%M %p
Format=11:11 PM
; Format=12:30 PM
OnUpdateAction=[!SetWindowPosition "#CURRENTCONFIGX#" "#CURRENTCONFIGY#" "0" "0"]
DynamicVariables=1

[Background]
Meter=Shape
X=0
Y=0
Shape=Rectangle 0,0,[SkinWidth],([TimeString:H] + (#Pad# * 2)),0 | Fill Color 107,170,255 | StrokeWidth 0
DynamicVariables=1

[TimeString]
Meter=String
X=#Pad#
Y=#Pad#
MeasureName=TimeMeasure
Text="%1"
FontSize=30
FontWeight=700
FontColor=255,255,255
InlinePattern=(.*)
InlineSetting="Case | Upper"
AntiAlias=1
DynamicVariables=1
Edit: replaced Imgur image with attachment for futureproofing.
You do not have the required permissions to view the files attached to this post.
Last edited by Crest on April 27th, 2023, 5:45 pm, edited 4 times in total.
User avatar
CodeCode
Posts: 1366
Joined: September 7th, 2020, 2:24 pm
Location: QLD, Australia

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by CodeCode »

This is the quick answer:

StringAlign=Right

If you have code that needs repair or improvements in this topic, then you should upload the rmskin (Create .rmskin package... button).
ƈǟռ'ȶ ʄɨӼ ɨȶ ɨʄ ɨȶ ǟɨռ'ȶ ɮʀօӄɛ - ʊռʟɛֆֆ ɨȶ ɨֆ ɨռ ƈօɖɛ.
Crest
Posts: 115
Joined: August 16th, 2013, 12:47 pm

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by Crest »

CodeCode wrote: April 26th, 2023, 4:53 pm This is the quick answer:

StringAlign=Right
In my testing this doesn't help since the background of the skin is being based on the string width, so it will always expand from the left edge regardless of the StringAlign alignment.

Unless I'm missing something else?

Eg, changing the following from my example time meter (from the skin in the OP spoiler tag) produces the same left-outward behavior when the time changes to a longer string:

Code: Select all

[TimeString]
Meter=String
X=([Background:W] - #Pad#)
StringAlign=Right
User avatar
balala
Rainmeter Sage
Posts: 16191
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by balala »

Crest wrote: April 26th, 2023, 4:59 pm In my testing this doesn't help since the background of the skin is being based on the string width, so it will always expand from the left edge regardless of the StringAlign alignment.

Unless I'm missing something else?
Yep, in fact you are missing something. What are you missing, is the fact that a Shape meter (what the [Background] meter is) can expand to both, right and left, if it's properly set. To get it working this way, we have to alter a few thing in your code:
  • We have to align the [TimeString] meter to right, as proposed by CodeCode above as well. Along with this, the meter has to be moved to right, increasing the value of its X option. Add the following StringAlign and alter the X option of this meter, as it follows:

    Code: Select all

    [TimeString]
    ...
    X=(200-#Pad#)
    ...
    StringAlign=Right
    ...
    See that in this case I moved the meter to right with 200 pixels, which seems to be a proper value. If it's not, just use any value you want, just make sure the X option of the [Background] meter is altered correspondingly, as described below.
  • Move the [Background] meter to right with the same value. Replace the X=0 option of this meter with X=200 (here you have to use the same value which you added above to the X option of the [TimeString] meter - make sure to use the proper value).
  • Finally you have to alter the shape option of the [Background] meter, to make the rectangle to extend to left, not to right (as by default). Use the following Shape option: Shape=Rectangle 0,0,(-1*[SkinWidth]),([TimeString:H] + (#Pad# * 2)),0 | Fill Color 107,170,255 | StrokeWidth 0 (see the third parameter, the width of the rectangle, which has been multiplied by -1 and this way the rectangle expands to left).
Crest
Posts: 115
Joined: August 16th, 2013, 12:47 pm

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by Crest »

balala wrote: April 26th, 2023, 6:35 pm Yep, in fact you are missing something. What are you missing, is the fact that a Shape meter (what the [Background] meter is) can expand to both, right and left, if it's properly set. To get it working this way, we have to alter a few thing in your code...
Thanks for the reply. I tried the suggested fixed X coord values and negative multiplication for the shape width and it indeed expands from the right edge (where the X value has been specified), which is nice.

An issue with this is that it clips into the left edge of the skin, truncating the content (here exaggerating the string length for demonstration):
Expanding from right issue - 1.gif
So I tried at first creating a separate small shape meter to the left side of the background shape meter just as a pseudo margin and adding that shape's width to the X coords values to try and force the background to always begin after it. However this wasn't successful as the background continued to expand from the right, ignoring the pseudo meter X coord addition after the string length expands.
Expanding from right issue - 2.gif
Code used for this pseudo margin attempt:

Code: Select all

[Rainmeter]
AccurateText=1
DynamicWindowSize=1
Update=1000

[Variables]
Pad=15
Margin=20

[SkinWidth]
Measure=Calc
Formula=[TimeString:W] + (#Pad# * 2)
DynamicVariables=1

[TimeMeasure]
Measure=Time
; Format=%I:%M %p
; Format=11:11 PM
Format=12:30 PMM
OnUpdateAction=[!SetWindowPosition "#CURRENTCONFIGX#" "#CURRENTCONFIGY#" "0" "0"]
DynamicVariables=1

[SkinLeftMargin]
Meter=Shape
X=0
Y=0
Shape=Rectangle 0,0,#Margin#,#Margin#,0 | Fill Color 255,0,0,255 | StrokeWidth 0
DynamicVariables=1

[Background]
Meter=Shape
X=([SkinLeftMargin:W] + 200)
Y=0
Shape=Rectangle 0,0,(-1 * [SkinWidth]),([TimeString:H] + (#Pad# * 2)),0 | Fill Color 107,170,255 | StrokeWidth 0
DynamicVariables=1

[TimeString]
Meter=String
X=([SkinLeftMargin:W] + 200 - #Pad#)
Y=#Pad#
MeasureName=TimeMeasure
Text="%1"
StringAlign=Right
FontSize=30
FontWeight=700
FontColor=255,255,255
InlinePattern=(.*)
InlineSetting="Case | Upper"
AntiAlias=1
DynamicVariables=1

While if I instead replace the 200 fixed value with the dynamic value [TextString:W] I end up back where I began, with the shape and text expanding from the left side again.

It's possible I'm just missing some aspect again and if so would appreciate any advice :) Otherwise I'm wondering if my original idea of physically moving the entire skin via X coords when the string changes is the only feasible alternative.

Edit: replaced Imgur images with attachments for futureproofing.
You do not have the required permissions to view the files attached to this post.
Last edited by Crest on April 27th, 2023, 9:07 am, edited 2 times in total.
User avatar
balala
Rainmeter Sage
Posts: 16191
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by balala »

Crest wrote: April 26th, 2023, 7:47 pm It's possible I'm just missing some aspect again and if so would appreciate any advice
Not sure if this is intentional or not, but in the last code, you have PMM, instead of PM. This is not a problem usually, however it extends the meter too much horizontally, causing the issue. You can increase the value 200, added to the X option of the [Background] and [TimeString] meters, to fix the issue.
In fact would be a good idea to introduce a variable, to can easier control the position of those meters. I added such a variable, naming it Extend. See below:

Code: Select all

[Rainmeter]
AccurateText=1
DynamicWindowSize=1
Update=1000

[Variables]
Pad=15
Margin=20
Extend=250

[SkinWidth]
Measure=Calc
Formula=[TimeString:W] + (#Pad# * 2)
DynamicVariables=1

[TimeMeasure]
Measure=Time
; Format=%I:%M %p
; Format=11:11 PM
Format=12:30 PMM
;OnUpdateAction=[!SetWindowPosition "#CURRENTCONFIGX#" "#CURRENTCONFIGY#" "0" "0"]
DynamicVariables=1

[SkinLeftMargin]
Meter=Shape
X=0
Y=0
Shape=Rectangle 0,0,#Margin#,#Margin#,0 | Fill Color 255,0,0,255 | StrokeWidth 0
DynamicVariables=1

[Background]
Meter=Shape
X=([SkinLeftMargin:W] + #Extend#)
Y=0
Shape=Rectangle 0,0,(-1 * [SkinWidth]),([TimeString:H] + (#Pad# * 2)),0 | Fill Color 107,170,255 | StrokeWidth 0
DynamicVariables=1

[TimeString]
Meter=String
X=([SkinLeftMargin:W] + #Extend# - #Pad#)
Y=#Pad#
MeasureName=TimeMeasure
Text="%1"
StringAlign=Right
FontSize=30
FontWeight=700
FontColor=255,255,255
InlinePattern=(.*)
InlineSetting="Case | Upper"
AntiAlias=1
Note that I commented out the OnUpdateAction option of the [TimeMeasure] measure. I don't think it is needed.
Crest
Posts: 115
Joined: August 16th, 2013, 12:47 pm

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by Crest »

balala wrote: April 26th, 2023, 8:24 pm Not sure if this is intentional or not, but in the last code, you have PMM, instead of PM. This is not a problem usually, however it extends the meter too much horizontally, causing the issue. You can increase the value 200, added to the X option of the [Background] and [TimeString] meters, to fix the issue.
Yeah, the 'PMM' was intentional, it was just to make the string length difference more obvious in the last post with the default Arial font (unlike the font used in the OP image). I should have used non-zero padded '1:11 PM' vs '12:30 PM' which would have been a more natural example of length difference.

I can see now that the workaround being suggested is creating extra, invisible whitespace to the left of the visible part of the skin.

This might be an okay compromise. A downside is the skin will snap to the left edge of the invisible whitespace since it's technically larger than the visible part of the skin bounds.

Visual demonstration of the proposed workaround compared to the concept from the OP (overlaid with pattern to show true bounds of skin):
Concept comparison.png
I'm thinking maybe a way to account for the prior time width, if I went with that method instead, would be:

- Creating some Lua script to return the prior minute/time value (ie: pass the current time to the script, get the prior time returned). This would avoid the need to write values to a text file.
- Then feed that value to an invisible string meter.
- Check that invisible meter's width.
- Compare the invisible meter's width with the current time meter width.
- If widths are different set AnchorX value to be the offset—but only for a single update of the skin, else it will continue to move the skin by that same amount if more updates than needed occur.

Edit: replaced Imgur image with attachment for futureproofing.
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 7185
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by Yincognito »

Crest wrote: April 27th, 2023, 9:01 amI'm thinking maybe a way to account for the prior time width, if I went with that method instead, would be [...]
I don't think you need Lua for this, or even overcomplicate things. What you want should be possible in multiple ways. Let me think a bit and see if I can come up with 2 or 3 of them - hopefully a straightforward variant would be included as well.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7185
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by Yincognito »

Alright, I don't think there's an easier way than this - no right aligning, no negative dimensions, no invisible space, no Lua, no prior width saving:

Code: Select all

[Variables]

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
OnUpdateAction=[!SetAnchor "100%" "0%"]

---Measures---

[Length]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=1
HighBound=11

[Text]
Measure=String
String=ABRACADABRA
RegExpSubstitute=1
Substitute="(?U)^.*(.{[Length]})$":"\1"
DynamicVariables=1

---Meters---

[Result]
Meter=String
SolidColor=107,170,255,255
FontSize=30
FontWeight=700
FontColor=255,255,255,255
Padding=10,10,10,10
InlinePattern=^(.*)$
InlineSetting="Case | Upper"
AntiAlias=1
MeasureName=Text
Text="%1"
DynamicVariables=1
The key is the !SetAnchor bang in the [Rainmeter] section, the rest is just to facilitate observation. The only downside would be if you needed to use dynamic variables in the bang (since the [Rainmeter] section generally doesn't like that), but then, it's not the case here. Let me know if you need other possible ways to do it, if by any chance this isn't what you're looking for.

P.S. To a certain extent, this works even if you replace the OnUpdateAction option with the OnRefreshAction one, or if you set the AnchorX and AnchorY options similarly in the Rainmeter.ini file (aka the current layout). The "100%" can be replaced by the "0R" or "0%R" equivalents, if desired.

P.S.S. If you really want a background set by a Shape meter before the String one, just copy paste the above String meter into an invisibly colored one before the Shape meter and use its dimensions to set the size of the shape coming after it. I do this in all skins from my suite to accurately "scale" them based on an arbitrary (but known beforehand) text content / font / size.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Crest
Posts: 115
Joined: August 16th, 2013, 12:47 pm

Re: Possible to expand/contract skin width from right edge instead of left? (Align)

Post by Crest »

Yincognito wrote: April 27th, 2023, 4:26 pm Alright, I don't think there's an easier way than this...

The key is the !SetAnchor bang in the [Rainmeter] section, the rest is just to facilitate observation.
Ah, thanks so much. This appears to be ideal and a very minimal change, too 👍