It is currently March 29th, 2024, 8:35 am

Scaling InputText Input Boxes and Dynamically Sized Border Images

Get help with creating, editing & fixing problems with skins
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by raiguard »

I am attempting to implement TransformationMatrix in an effort to make my skins scalable. And for the most part, it is going very well! But there are two issues that I need to figure out how to solve:

1. Scaling InputText plugin input boxes
2. Scaling a dynamically sized border image

I made an example skin that shows off both of these issues at once:
transform.gif
(Please note that this skin implements my dynamic positioning system, so there is a bit of extra fluff that doesn't directly pertain to my issue.)

As you can see, when the skin is scaled to anything except for 1.00, despite the dimensions of the inputtext input box being correct, the text remains at the x1 scale factor. I tried multiplying the FontSize value by the scale factor, but that didn't have very good results. I am at a loss as to how to solve this.

The border image is simply a transparent square with a 1-pixel-wide white outline. I use the ScaleMargins option to be able to resize this border image to whatever dimensions I require, and use it for outlining input boxes, line graphs, and the gadget background, as you can see here:
2018-10-20 23_58_38-.png
This works great at a x1 scale factor. However, the moment you change the scale factor, the image becomes blurry and inconsistent. A possible solution would be to not use an image with ScaleMargins, but instead use four separate image meters that simply use SolidColor, but I would like to be able to do it with one meter if possible.

I have attached a .RMSKIN for this demo. I have also included the skin code below, and attached the relevant image separately, just in case.

Code: Select all

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

[Variables]
; Positioning
bgOffset=5
bgWidth=45
contentMarginAbs=3
contentMargin=(#contentMarginAbs# + #bgOffset# - 1)
contentMarginRight=(#bgWidth# - #contentMarginAbs# + #bgOffset# - 1)
contentWidth=(#contentMarginRight# - #contentMargin#)
; Scaling
scale=1.00
transformationMatrix=#Scale#;0;0;#Scale#;#Scale#;#Scale#
; Colors
colorInputBoxText=170,170,170
colorInputBoxBg=30,30,30
colorInputBoxBorder=50,50,50
; Font
fontFace=Helvetica

[StyleInputBoxBackground]
ImageName=#@#border.png
ImageTint=#colorInputBoxBorder#
SolidColor=#colorInputBoxBg#
X=#contentMargin#
Y=#contentMargin#
W=#contentWidth#
H=19
ScaleMargins=2,2,2,2
TransformationMatrix=#transformationMatrix#

[StyleInputBoxText]
FontSize=10
FontFace=#fontFace#
FontColor=#colorInputBoxText#
X=3r
Y=1r
W=([&[#CURRENTSECTION]Background:W] - 6)
H=16
Padding=0,-1,0,0
ClipString=1
DynamicVariables=1
AntiAlias=1
TransformationMatrix=#transformationMatrix#

[StyleMouseRegion]
SolidColor=255,0,0,0
DynamicVariables=1
X=([#CURRENTSECTION#_:X] * #scale# + #scale#)
Y=([#CURRENTSECTION#_:Y] * #scale# + #scale#)
W=([#CURRENTSECTION#_:W] * #scale#)
H=([#CURRENTSECTION#_:H] * #scale#)

; ----- Measures -----

[MeasureInputText]
Measure=Plugin
Plugin=InputText
; Use a different color, for debugging
SolidColor=45,45,45
FontColor=#colorInputBoxText#
FontSize=10
FontFace=#fontFace#
UpdateDivider=-1
FocusDismiss=1
InputLimit=30
Antialias=1
DynamicVariables=1
Command1=[!WriteKeyValue Variables scale "$UserInput$"][!Refresh] DefaultValue="#scale#" X=[MeterScaleInputBox:X] Y=[MeterScaleInputBox:Y] W=[MeterScaleInputBox:W] H=[MeterScaleInputBox:H]

; ----- Meters -----

[MeterBackgroundMargin]
Meter=Image
SolidColor=255,255,255,50
X=-1
Y=-1
W=((#bgWidth# + (#bgOffset# * 2)) * #scale#)
H=([MeterBackgroundHeight:Y] * #scale#)
DynamicVariables=1
Group=BgMeters
TransformationMatrix=#transformationMatrix#

[MeterBackground]
Meter=Image
SolidColor=15,15,15
X=(#bgOffset# - 1)
Y=(#bgOffset# - 1)
W=#bgWidth#
H=([MeterBackgroundHeight:Y] - (#bgOffset# * 2))
ScaleMargins=2,2,2,2
DynamicVariables=1
Group=BgMeters
TransformationMatrix=#transformationMatrix#

[MeterScaleInputBox_Background]
Meter=Image
MeterStyle=StyleInputBoxBackground

[MeterScaleInputBox_]
Meter=String
MeterStyle=StyleInputBoxText
Text=#scale#

[MeterBgAdjustor]
Meter=Image
X=r
Y=4R
TransformationMatrix=#transformationMatrix#

[MeterBackgroundHeight]
Meter=Image
SolidColor=255,255,255,255
X=0
Y=(#contentMarginAbs# + #bgOffset#)R
W=((#bgWidth# + (#bgOffset# * 2)) * #scale#)
H=1
DynamicVariables=1
Group=BgMeters
TransformationMatrix=#transformationMatrix#

; ----- Mouse Regions -----

[MeterScaleInputBox]
Meter=Image
MeterStyle=StyleMouseRegion
LeftMouseUpAction=[!CommandMeasure MeasureInputText "Executebatch 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
rxtd
Posts: 100
Joined: April 30th, 2017, 11:51 am

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by rxtd »

raiguard wrote: October 21st, 2018, 6:01 am This works great at a x1 scale factor. However, the moment you change the scale factor, the image becomes blurry and inconsistent. A possible solution would be to not use an image with ScaleMargins, but instead use four separate image meters that simply use SolidColor, but I would like to be able to do it with one meter if possible.
You can use Shape meter. To get outline you can either combine two rectangles (using Exclude) or use rectangle with stroke (shifted to 0.5*stroke_width in both dimensions to get stroke where it needs to be and to have thin stroke with 1x scale).
For example: Shape=Rectangle 1.5,16.5,227,59|Fill Color 0,0,0,0|StrokeWidth 1|Stroke Color 20,20,20,255
As far as I know, stroke is not affected by transformation matrices, and if you define it as 1px, it will stay so. Adjust it manually, if needed.
Also Shape meter works with device independent pixels, so uneven size values will lead to slightly blurred look. To avoid it you can use Round formula in shape definition instead of transformation matrix.
For example, Shape=Rectangle (Round(1*#scale#)+0.5),(Round(16*#scale#)+0.5),(Round(227*#scale#)),(Round(59*#scale#))
User avatar
balala
Rainmeter Sage
Posts: 16110
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by balala »

Beside rxtd's reply note that you can't use the ScaleMargins option if the Image meter is resized through the TransformationMatrix option, just if you resize it setting the appropriate width and height, through W and H options.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by jsmorley »

As to scaling InputText. It's not a meter, but an external Windows control element, and the only way to scale it is with W / H / FontSize.

FontSize is in integer "points", so it will be tricky to get incremental changes that look and fit right. I would be tempted to design things in such a way that inputs are a fixed size, and don't scale with the rest of the skin.

As to outline borders, I would certainly use the Shape meter, and not Image meters. Shape has its own built-in scaling capabilities.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by jsmorley »

Code: Select all

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

[Variables]
ScaleFactor=1.0

[MeterShape]
Meter=Shape
X=15
Y=15
Shape=Path MyPath1 | StrokeWidth (Ceil(6 * #ScaleFactor#))  | Fill LinearGradient MyGradient
MyPath1=0,0 | LineTo 200,0 | ArcTo 200,200 | LineTo 0,200 | CurveTo 0,0,50,100 | ClosePath 1
MyGradient=180 | 50,50,50,255 ; 0.0 | 255,255,255,255 ; 1.0
Shape2=Ellipse 90,100,100
Shape3=Ellipse 200,100,50
Shape4=Combine Shape | Union Shape2 | XOR Shape3 | Scale #ScaleFactor#,#ScaleFactor#,0,0,0,0
DynamicVariables=1
MouseScrollUpAction=[!SetVariable ScaleFactor "(Clamp(#ScaleFactor# - 0.05,0.2,2.5))"][!UpdateMeter *][!Redraw]
MouseScrollDownAction=[!SetVariable ScaleFactor "(Clamp(#ScaleFactor# + 0.05,0.2,2.5))"][!UpdateMeter *][!Redraw]
LeftMouseUpAction=[!Refresh]
GIF.gif
You do not have the required permissions to view the files attached to this post.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5384
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by eclectic-tech »

I would interject that the Scaling TransformationMatrix formula's discussed recently are designed to scale meters that use Width and Height for other purposes than controlling the image size (ROTATOR METERS specifically, and a few others).

There are simpler techniques that can be used to scale other meters; for most meters adding a #Scale# value to X, Y, W, and H suffice.

In other words, the TransformationMatrix Scale formulas are not an "one-size-fits-all" answer for creating skins that can be easily scaled.

I have used both of these techniques in various skins effectively. Depending on the meter type, it is up to the author to choose the technique that best fits their desired effect.

As JSMorley shows each meter type may require a slightly different approach to obtain the desired result.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by raiguard »

Thanks for all the input guys. For now I have decided to restrict the scaling to the gadgets themselves, which will eliminate the need to scale the input boxes (and saves me a TON of work as well!). I had tried shape meters before but was dismayed when the minimum strokewidth appeared to be 2, despite it being set to 1. I'll have to go test rxtd's method and see if that works.

If I ever find a consistent way to scale the input boxes I'll be sure to post about it. :)
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by jsmorley »

Code: Select all

[MeterBox]
Meter=Shape
X=1
Y=1
Shape=Rectangle 0.5,0.5,400,300 | StrokeWidth 0.5 | Stroke Color 255,255,255,255 | Fill Color 0,0,0,255
7.png

Code: Select all

[MeterBox]
Meter=Shape
X=1
Y=1
Shape=Rectangle 0.5,0.5,400,300 | StrokeWidth 1 | Stroke Color 255,255,255,255 | Fill Color 0,0,0,255
9.png
You do not have the required permissions to view the files attached to this post.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by raiguard »

I managed to make it work! I ended up using the two rectangles method rather than the offset stroke method, because the latter was causing all sorts of issues with my pixel-perfect placement of things. Using two rectangles ended up being way easier. I also managed to consolidate both the background and the margin into one meter as well!

Anyway, here's an updated example and GIF. Use the mouse wheel to scale and click to toggle the background border on and off. I used ugly colors for visibility: White is the margin (normally invisible), yellow is the border, red is the background, and blue is the dummy content.
transform.gif

Code: Select all

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

[Variables]
; Positioning
bgOffset=5
bgWidth=45
contentMarginAbs=3
contentMargin=(#contentMarginAbs# + #bgOffset# - 1)
contentMarginRight=(#bgWidth# - #contentMarginAbs# + #bgOffset# - 1)
contentWidth=(#contentMarginRight# - #contentMargin#)
; Scaling
scale=5
transformationMatrix=#scale#;0;0;#scale#;#scale#;#scale#
; Colors
colorBg=200,50,50
colorBorder=200,200,50
; Settings
showBgBorder=1

; ----- Measures -----

[MeasureInputText]
Measure=Plugin
Plugin=InputText
; Use a different color, for debugging
SolidColor=45,45,45
FontColor=#colorInputBoxText#
FontSize=10
FontFace=#fontFace#
UpdateDivider=-1
FocusDismiss=1
InputLimit=30
Antialias=1
DynamicVariables=1
Command1=[!WriteKeyValue Variables scale "$UserInput$"][!Refresh] DefaultValue="#scale#" X=[MeterScaleInputBox:X] Y=[MeterScaleInputBox:Y] W=[MeterScaleInputBox:W] H=[MeterScaleInputBox:H]

; ----- Meters -----

[MeterBackground]
Meter=Shape
Shape=Rectangle (#bgOffset# * #scale#),(#bgOffset# * #scale#),(#bgWidth# * #scale#),(([MeterBackgroundHeight:Y] - (#bgOffset# * 2)) * #scale#) | StrokeWidth 0 | Fill Color #colorBorder#,((#showBgBorder# = 1) ? 255 : 0)
Shape2=Rectangle ((#bgOffset# + #showBgBorder#) * #scale#),((#bgOffset# + #showBgBorder#) * #scale#),((#bgWidth# - (#showBgBorder# * 2)) * #scale#),(([MeterBackgroundHeight:Y] - (#bgOffset# * 2) - (#showBgBorder# * 2)) * #scale#) | StrokeWidth 0 | Fill Color #colorBg#
X=0
Y=0
W=((#bgWidth# + (#bgOffset# * 2)) * #scale#)
H=([MeterBackgroundHeight:Y] * #scale#)
SolidColor=255,255,255,50
DynamicVariables=1
Group=Background
; Debugging
MouseScrollUpAction=[!WriteKeyValue Variables scale "(clamp((#scale# + 0.5),1,5))"][!Refresh]
MouseScrollDownAction=[!WriteKeyValue Variables scale "(clamp((#scale# - 0.5),1,5))"][!Refresh]
LeftMouseUpAction=[!WriteKeyValue Variables showBgBorder "(abs(#showBgBorder# - 1))"][!Refresh]
MouseActionCursor=0

[MeterDummyContent]
Meter=Image
SolidColor=50,50,200
X=#contentMargin#
Y=#contentMargin#
W=#contentWidth#
H=20
TransformationMatrix=#transformationMatrix#

[MeterBackgroundHeight]
Meter=Image
SolidColor=255,255,255,0
X=0
Y=(#contentMarginAbs# + #bgOffset# + 1)R
W=((#bgWidth# + (#bgOffset# * 2)) * #scale#)
H=1
DynamicVariables=1
Group=Background
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
eclectic-tech
Rainmeter Sage
Posts: 5384
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Scaling InputText Input Boxes and Dynamically Sized Border Images

Post by eclectic-tech »

raiguard wrote: October 24th, 2018, 2:14 am I managed to make it work! I ended up using the two rectangles method rather than the offset stroke method, because the latter was causing all sorts of issues with my pixel-perfect placement of things. Using two rectangles ended up being way easier. I also managed to consolidate both the background and the margin into one meter as well!
Whoa! :o

You may be overthinking this...
You managed to scale the boxes, but you didn't scale the actual "input box". :uhuh:

I think your desired result can be done by using 'TransformationMatrix' in meters, and 'Scale' in shape meters rather than by adding new formulas.

NOTE: TransformationMatrix and Shape Meter Scale do not scale the same way by default.

TransformationMatrix normally scales from the top-left corner of the meter.
You can force it to use a different point by changing the last to numbers.

Shape meter's normally scale from the center of the shape.
So you need to set the scaling point to 0,0 to match the default TransformationMatrix scale.
The parameter would be: Scale #Scale#,#Scale#,0,0

Rather than develop convoluted formulas and multiple variables, I think you can obtain the desired result letting the TransformationMatrix and Shape Meter Scale do the calculating; you simply need to match the scaling point and add the scale to the meter initial positions (and sometimes their size). Depending on the meter and the desired result, how you apply these will differ slightly, but I do not think you need to "reinvent the wheel" with more formulas.

Here is my (poiru's) Google Search skin (some color variables added) that matches the input box and background using those techniques.

Code: Select all

; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------

[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Update=1000
AccurateText=1
DynamicWindowSize=1
Group=#RootConfig#

MouseScrollUpAction=[!CommandMeasure MeasureScaleIt "Execute 1"]
MouseScrollDownAction=[!CommandMeasure MeasureScaleIt "Execute 2"]
MiddleMouseUpAction=[!Refresh]

[Metadata]
; Contains basic information of the skin.
Description=Allows searching through Google.
License=Creative Commons BY-NC-SA 4.0
Version=1.2018.10.23-A

; Include allow the addition of an external file with code that can be used in multiple skins
; @includesystemColors=#@#includes\SysColors.inc

[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
; Sets the skin height based on the number of items 
ItemLines=1
Scale=1

AccentColor=40,40,200
colorText=255,255,255
fontName=Trebuchet MS
colorBar=128,128,128
Win8Color=240,240,28
fillColor=200,40,40
TextSize=8

; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------

[measureInput]
; The InputText.dll plugin has special powers: it allows user input.
; However, it's not the easiest way to start learning Rainmeter. Get a
; hold of the basics, and then check out the manual entry for InputText.
Measure=Plugin
Plugin=InputText.dll
DynamicVariables=1
SolidColor=20,20,20,255
StringAlign=LEFT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=#AccentColor#,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=(#textSize#*#Scale#)
X=(10*#Scale#)
Y=(27*#Scale#)
W=(170*#Scale#)
H=(17*#Scale#)
FocusDismiss=1
DefaultValue=""
Command1=["http://www.google.com/search?q=$UserInput$"]
UpdateDivider=86400

; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------

[styleTitle]
StringAlign=CENTER
InlineSetting=Case | UPPER
InlineSetting2=Weight | 900
InlineSetting3=Size | 10
StringEffect=SHADOW
FontEffectColor=#AccentColor#,50
FontColor=#colorText#
FontFace=#fontName#
AntiAlias=1
ClipString=2
ClipStringW=180
DynamicVariables=1

[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=#AccentColor#,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
DynamicVariables=1

[styleSeperator]
SolidColor=#colorBar#
DynamicVariables=1
X=(10*#Scale#)
Y=(1*#Scale#)R
W=(170*#Scale#)
H=(1*#Scale#)

; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------

[MeterBackground]
Meter=Shape
DynamicVariables=1
X=1
Y=1
Shape=Rectangle 0,0,190,(34+(#ItemLines#*17)),2 | Fill Color #fillColor# | StrokeWidth (1*#Scale#) | Stroke Color #Win8Color# | Scale #Scale#,#Scale#,0,0

[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=((190*#Scale#)/2)
Y=(10*#Scale#)
W=190
H=18
Text="Google"
; Scale Center 
TransformationMatrix=#Scale#;0;0;#Scale#;((1-#Scale#)*([#CURRENTSECTION#:X]+[#CURRENTSECTION#:W]/2));((1-#Scale#)*([#CURRENTSECTION#:Y]+[#CURRENTSECTION#:H]/2))

[meterSearch]
Meter=STRING
MeterStyle=styleLeftText
X=(10*#Scale#)
Y=(30*#Scale#)
W=(170*#Scale#)
H=(14*#Scale#)
Text="Search..."
LeftMouseUpAction=!PluginBang "measureInput ExecuteBatch 1"
; Scale Left 
TransformationMatrix=#Scale#;0;0;#Scale#;((1-#Scale#)*([#CURRENTSECTION#:X]));((1-#Scale#)*([#CURRENTSECTION#:Y]))

[meterSeperator]
Meter=IMAGE
MeterStyle=styleSeperator

[MeasureScaleIt]
Measure=Plugin
Plugin=ActionTimer
ActionList1=ScaleUp
ScaleUp=[!SetVariable Scale "(Clamp(#Scale#+0.5,1,3))"][!WriteKeyValue Variables Scale "(Clamp(#Scale#+0.5,1,3))"]#U#
ActionList2=ScaleDown
ScaleDown=[!SetVariable Scale "(Clamp(#Scale#-0.5,1,3))"][!WriteKeyValue Variables Scale "(Clamp(#Scale#-0.5,1,3))"]#U#
DynamicVariables=1
Hope this helps, but whether you use it is up to you. :great: