It is currently April 19th, 2024, 11:15 am

Text filter

Get help with creating, editing & fixing problems with skins
aetasoul
Posts: 11
Joined: August 7th, 2021, 6:49 am

Text filter

Post by aetasoul »

Hi all,
I'd like to create a contacts list skin. I've near 20 phone numbers to show (with person name).

What I'm trying to do is to create a searchable contact list by name.
skin.png

Code: Select all

[Rainmeter]
Update=1000
Background=#@#Background.png
BackgroundMode=3
BackgroundMargins=0,34,0,14
DynamicWindowSize=1

[Metadata]
Name=Numeri
Author=aetasoul
Information=Displays internal phones numbers.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0

[Variables]
fontName=Trebuchet MS
textSize=9
colorBar=235,170,0,255
colorText=255,255,255,205
searchValue=

[measureInput]
Measure=Plugin
Plugin=InputText.dll
SolidColor=20,20,20,255
StringAlign=Left
StringCase=None
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
X=10
Y=38
W=188
H=17
FocusDismiss=1
DefaultValue=""
Command1=[!SetVariable "searchValue" $UserInput$]
UpdateDivider=86400

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

[styleTitle]
StringAlign=Center
StringCase=Upper
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1

[styleLeftText]
StringAlign=Left
; Meters using styleLeftText will be left-aligned.
StringCase=None
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1

[styleRightText]
StringAlign=Right
StringCase=None
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1

[styleBar]
BarColor=#colorBar#
BarOrientation=HORIZONTAL
SolidColor=255,255,255,15

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

[meterTitle]
Meter=String
MeterStyle=styleTitle
X=100
Y=12
W=190
H=18
Text=Numeri

[meterSearch]
Meter=String
MeterStyle=styleLeftText
X=10
Y=40
W=190
H=14
Text=Search...
LeftMouseUpAction=[!CommandMeasure measureInput "ExecuteBatch 1"]

[meterLabel1]
Meter=String
MeterStyle=styleLeftText 
X=10
Y=60
W=190
H=14
Text=Person1

[meterValue1]
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
W=190
H=14
Text=NUM
NumOfDecimals=1
AutoScale=1

[meterLabel2]
Meter=String
MeterStyle=styleLeftText 
X=10
Y=80
W=190
H=14
Text=Person2

[meterValue2]
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
W=190
H=14
Text=NUM
NumOfDecimals=1
AutoScale=1

[meterLabel3]
Meter=String
MeterStyle=styleLeftText
X=10
Y=100
W=190
H=14
Text=Person3

[meterValue3]
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
W=190
H=14
Text=NUM
NumOfDecimals=1
AutoScale=1

[meterLabel4]
Meter=String
MeterStyle=styleLeftText
X=10
Y=120
W=190
H=14
Text=Person4

[meterValue4]
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
W=190
H=14
Text=NUM
NumOfDecimals=1
AutoScale=1
I was able to save the search text in a variable, but now I don't know how to filter the rows. The logic is:
  • The text match some name: Only the rows that match are shown
  • The text does not match the names: All the rows are shown.
This is possible? Any tips?
You do not have the required permissions to view the files attached to this post.
User avatar
CodeCode
Posts: 1365
Joined: September 7th, 2020, 2:24 pm
Location: QLD, Australia

Re: Text filter

Post by CodeCode »

Look through this: https://docs.rainmeter.net/manual/measures/general-options/ifconditions/

Should get you where you are aiming.

There are other things that may apply, like making your list dynamic. And making a variable list that works with it.
ƈǟռ'ȶ ʄɨӼ ɨȶ ɨʄ ɨȶ ǟɨռ'ȶ ɮʀօӄɛ - ʊռʟɛֆֆ ɨȶ ɨֆ ɨռ ƈօɖɛ.
aetasoul
Posts: 11
Joined: August 7th, 2021, 6:49 am

Re: Text filter

Post by aetasoul »

CodeCode wrote: August 17th, 2021, 1:00 pm Look through this: https://docs.rainmeter.net/manual/measures/general-options/ifconditions/

Should get you where you are aiming.

There are other things that may apply, like making your list dynamic. And making a variable list that works with it.
Thank you CodeCode.

Looking through https://docs.rainmeter.net/manual/measures/general-options/ifconditions/ I see that the ifconditions can be used only with numeric values.
Note: IfCondition can only be used to evaluate a numeric mathematical formula. No string values may be used in the condition test. See IfMatchActions to test and take action on string values.
There is something else to work with strings?

About the list variable, I can't find on the docs how to declare it and assign values, any tips?

Thank you!
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Lua based Searchable List/Table

Post by death.crafter »

A searchable contact skin. Keep what you like.
  • You have to format the contacts in Contacts.inc in Resources folder like this:

    Code: Select all

    [1]
    Name=Albus Dumbledore
    Phone=7685346870
    Email=theheadmaster@hogwarts.org
    Image=#@#Icons\user
    
    [2]
    Name=Cho Chang
    Phone=6745368798
    Email=harrycheatedonme@hogwarts.org
    Image=#@#Icons\user
    
  • The section names, i.e, [1], [2] are not supposed to be indexed. They can be anything e.g. [XYZ], [ABC].
    But the order in which they are declared are the order in which they are shown. Here Cho Chang will be shown after Albus.
  • Here, Albus will be shown after Cho Chang.

    Code: Select all

    [2]
    Name=Cho Chang
    Phone=6745368798
    Email=harrycheatedonme@hogwarts.org
    Image=#@#Icons\user
    
    [1]
    Name=Albus Dumbledore
    Phone=7685346870
    Email=theheadmaster@hogwarts.org
    Image=#@#Icons\user
    
  • Except Name you can change, add or remove any option. You can use it in your code as [&Script:Contacts(Index, 'OptionName')]
  • If you use [&Script:Contacts(n, 'Image')] but haven't defined the option Image in contacts list, then it will default to #@#Icons\user.png
  • The variable MaxListItems define how many contacts to index at once.
  • The variable ScrollIndex=0 is used to scroll, so it must be kept intact. And you shouldn't use MaxScrollIndex as a variable as it is used internally.
  • To go back after searching, just click on search and enter. The command for script measure is "GetContacts()", without parameters.
  • To search a term, command is "GetContacts('<SearchTerm>')", with the single quotes, without angular brackets, e.g
    [!CommandMeasure Script "GetContacts('Mary')"]
Contacts_v1.0.0.rmskin
If it were powershell, I could have dictionarized it, but it isn't that integrated with Rainmeter so too much work.

Edit:
I forgot the previews lol.
Screenshot 2021-08-18 210935.png
Screenshot 2021-08-18 210836.png
You do not have the required permissions to view the files attached to this post.
from the Realm of Death
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Text filter

Post by death.crafter »

There was a bug in pattern matching.

Oh, I forgot to mention you can use lua pattern matching to get results.

E.g. ^[^ABC] will give all the contacts not starting from A, B or C.

Also, if you use any character from the lua reserved characters( ( ) % . + - * [ ? ^ $ ), search becomes case senitive.
To match one of these characters, you have to escape them using %, e.g. to match % use %%.

Here is the fixed version:
Contacts_v1.0.1.rmskin
You do not have the required permissions to view the files attached to this post.
from the Realm of Death
aetasoul
Posts: 11
Joined: August 7th, 2021, 6:49 am

Re: Text filter

Post by aetasoul »

death.crafter wrote: August 18th, 2021, 5:59 pm There was a bug in pattern matching.

Oh, I forgot to mention you can use lua pattern matching to get results.

E.g. ^[^ABC] will give all the contacts not starting from A, B or C.

Also, if you use any character from the lua reserved characters( ( ) % . + - * [ ? ^ $ ), search becomes case senitive.
To match one of these characters, you have to escape them using %, e.g. to match % use %%.

Here is the fixed version:
Contacts_v1.0.1.rmskin
WOW! :o

This is impressive as skin, super! Thank you very much for your help, with this skin I solved all the issues, also on another skin that I'm making to convert DEC to HEX, BIN, OCT and vice-versa.
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Text filter

Post by death.crafter »

aetasoul wrote: August 19th, 2021, 3:26 pm WOW! :o

This is impressive as skin, super! Thank you very much for your help, with this skin I solved all the issues, also on another skin that I'm making to convert DEC to HEX, BIN, OCT and vice-versa.
Good to know that it helped :D
from the Realm of Death
User avatar
Yincognito
Rainmeter Sage
Posts: 7125
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Text filter

Post by Yincognito »

death.crafter wrote: August 19th, 2021, 4:42 pmGood to know that it helped :D
It helped for sure this time, but even though you did explain how it works, I'm not sure the OP learned something out of it in order to be able to do it on his own next time, whether it's in Lua or native Rainmeter code, considering it's his 5th post here and he's most likely still a beginner. :confused:
aetasoul wrote: August 19th, 2021, 3:26 pm...also on another skin that I'm making to convert DEC to HEX, BIN, OCT and vice-versa.
For this skin, based on your own code (and yes, you were correct with your unanswered question of "There is something else to work with strings?", as that is the key; it's called IfMatch - the IfCondition equivalent, but for strings):

Code: Select all

[Variables]
fontName=Trebuchet MS
textSize=9
colorBar=235,170,0,255
colorText=255,255,255,205
searchValue=
Label1=Person1
Label2=Person2
Label3=Person3
Label4=Person4
Value1=Value1
Value2=Value2
Value3=Value3
Value4=Value4

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
Background=#@#Background.png
BackgroundMode=3
BackgroundMargins=0,34,0,14

[Metadata]
Name=Numeri
Author=aetasoul
Information=Displays internal phones numbers.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0

---Measures---

[measureInput]
Measure=Plugin
Plugin=InputText
SolidColor=20,20,20,255
StringAlign=Left
StringCase=None
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
X=[meterSearch:X]
Y=[meterSearch:Y]
W=[meterSearch:W]
H=[meterSearch:H]
FocusDismiss=1
DefaultValue=""
Command1=[!SetVariable searchValue "$UserInput$"][!UpdateMeasure measureInput][!UpdateMeasureGroup ContactGroup][!UpdateMeterGroup ContactGroup][!Redraw]
UpdateDivider=-1

[measureLabel1]
Measure=String
String=#Label1#
UpdateDivider=-1

[measureValue1]
Measure=String
String=#Value1#
UpdateDivider=-1

[measureContact1]
Group=ContactGroup
Measure=String
String=#Label1##CRLF##Value1#
UpdateDivider=-1
IfMatch=(?siU)(?:^$|^.*[measureInput:EscapeRegExp].*$)
IfMatchAction=[!ShowMeterGroup Contact1Group]
IfNotMatchAction=[!HideMeterGroup Contact1Group]
IfMatchMode=1
DynamicVariables=1

[measureLabel2]
Measure=String
String=#Label2#
UpdateDivider=-1

[measureValue2]
Measure=String
String=#Value2#
UpdateDivider=-1

[measureContact2]
Group=ContactGroup
Measure=String
String=#Label2##CRLF##Value2#
UpdateDivider=-1
IfMatch=(?siU)(?:^$|^.*[measureInput:EscapeRegExp].*$)
IfMatchAction=[!ShowMeterGroup Contact2Group]
IfNotMatchAction=[!HideMeterGroup Contact2Group]
IfMatchMode=1
DynamicVariables=1

[measureLabel3]
Measure=String
String=#Label3#
UpdateDivider=-1

[measureValue3]
Measure=String
String=#Value3#
UpdateDivider=-1

[measureContact3]
Group=ContactGroup
Measure=String
String=#Label3##CRLF##Value3#
UpdateDivider=-1
IfMatch=(?siU)(?:^$|^.*[measureInput:EscapeRegExp].*$)
IfMatchAction=[!ShowMeterGroup Contact3Group]
IfNotMatchAction=[!HideMeterGroup Contact3Group]
IfMatchMode=1
DynamicVariables=1

[measureLabel4]
Measure=String
String=#Label4#
UpdateDivider=-1

[measureValue4]
Measure=String
String=#Value4#
UpdateDivider=-1

[measureContact4]
Group=ContactGroup
Measure=String
String=#Label4##CRLF##Value4#
UpdateDivider=-1
IfMatch=(?siU)(?:^$|^.*[measureInput:EscapeRegExp].*$)
IfMatchAction=[!ShowMeterGroup Contact4Group]
IfNotMatchAction=[!HideMeterGroup Contact4Group]
IfMatchMode=1
DynamicVariables=1

---Styles---

[styleTitle]
StringAlign=Center
StringCase=Upper
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1

[styleLeftText]
StringAlign=Left
StringCase=None
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
Padding=0,2,0,2
ClipString=1

[styleRightText]
StringAlign=Right
StringCase=None
StringStyle=Bold
StringEffect=Shadow
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
Padding=0,2,0,2
ClipString=1

[styleBar]
BarColor=#colorBar#
BarOrientation=HORIZONTAL
SolidColor=255,255,255,15

---Meters---

[meterTitle]
Meter=String
MeterStyle=styleTitle
X=100
Y=12
W=190
H=18
Text=Numeri

[meterSearch]
Meter=String
MeterStyle=styleLeftText
X=10
Y=38
W=188
H=17
Text=Search...
LeftMouseUpAction=[!CommandMeasure measureInput "ExecuteBatch All"]
DynamicVariables=1

[meterLabel1]
Group=ContactGroup | Contact1Group
Meter=String
MeterStyle=styleLeftText 
X=10
Y=60
MeasureName=measureLabel1
Text=%1

[meterValue1]
Group=ContactGroup | Contact1Group
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
MeasureName=measureValue1
Text=%1
NumOfDecimals=1
AutoScale=1

[meterLabel2]
Group=ContactGroup | Contact2Group
Meter=String
MeterStyle=styleLeftText 
X=10
Y=0R
MeasureName=measureLabel2
Text=%1

[meterValue2]
Group=ContactGroup | Contact2Group
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
MeasureName=measureValue2
Text=%1
NumOfDecimals=1
AutoScale=1

[meterLabel3]
Group=ContactGroup | Contact3Group
Meter=String
MeterStyle=styleLeftText
X=10
Y=0R
MeasureName=measureLabel3
Text=%1

[meterValue3]
Group=ContactGroup | Contact3Group
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
MeasureName=measureValue3
Text=%1
NumOfDecimals=1
AutoScale=1

[meterLabel4]
Group=ContactGroup | Contact4Group
Meter=String
MeterStyle=styleLeftText
X=10
Y=0R
MeasureName=measureLabel4
Text=%1

[meterValue4]
Group=ContactGroup | Contact4Group
Meter=String
MeterStyle=styleRightText
X=200
Y=0r
MeasureName=measureValue4
Text=%1
NumOfDecimals=1
AutoScale=1
And yes, this can have scrolling as well, with similar addition to death.crafter's implementation. This can search both contact "names" and "numbers", since it merges them in [measureContact...] measures, then uses IfMatch to test whether the contents of [measureInput] (regular expression escaped using the :EscapeRegExp parameter) is found in the previously merged string.

Here's a base converter I wrote some time ago, for DEC to any base up to base 36. Maybe you can use it as a "base" (see what I just did here? :D ) to add the reverse:

Code: Select all

[Variables]
Number=2744
Quotient=(#Number#)
Result=""
Base=20

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

---Measures---

[MeasureConvert]
Measure=Calc
Formula=(#Quotient#%#Base#)
UpdateDivider=-1
RegExpSubstitute=1
Substitute="^10$":"A","^11$":"B","^12$":"C","^13$":"D","^14$":"E","^15$":"F","^16$":"G","^17$":"H","^18$":"I","^19$":"J","^20$":"K","^21$":"L","^22$":"M","^23$":"N","^24$":"O","^25$":"P","^26$":"Q","^27$":"R","^28$":"S","^29$":"T","^30$":"U","^31$":"V","^32$":"W","^33$":"X","^34$":"Y","^35$":"Z"
IfCondition=((#Quotient#)<>0)
IfTrueAction=[!SetVariable Result "[MeasureConvert]#Result#"][!SetVariable Quotient (Trunc(#Quotient#/#Base#))][!UpdateMeasure "MeasureConvert"]
IfConditionMode=1
DynamicVariables=1

---Meter---

[MeterConvert]
Meter=STRING
X=5
Y=5
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
Text="Number = #Number##CRLF#Base   = #Base##CRLF#Result = #Result#"
DynamicVariables=1
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Text filter

Post by death.crafter »

Yincognito wrote: August 19th, 2021, 5:21 pm It helped for sure this time, but even though you did explain how it works, I'm not sure the OP learned something out of it in order to be able to do it on his own next time, whether it's in Lua or native Rainmeter code, considering it's his 5th post here and he's most likely still a beginner. :confused:
I am always here for questions. :D

P.S. I don't contest the implementation but I wouldn't create 150 meters for 50 contacts. Or even 60 for 20 :confused:
from the Realm of Death
User avatar
Yincognito
Rainmeter Sage
Posts: 7125
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Text filter

Post by Yincognito »

death.crafter wrote: August 19th, 2021, 5:59 pmI am always here for questions. :D
Indeed - learning a language (whether it's Rainmeter's INI syntax or Lua) just from answers to specific questions would be a first though. I'd be like :jawdrop if you can show me an "apprentice" that managed that. Maybe your friend Jax? :???:

For me, it took a couple of days with lots of tabs open in my browser to say I can reasonably (according to my high expectation self-review) do things in Lua. In Rainmeter, though easier, it took longer and I still discover new things day by day...
death.crafter wrote: August 19th, 2021, 5:59 pmP.S. I don't contest the implementation but I wouldn't create 150 meters for 50 contacts. Or even 60 for 20 :confused:
I don't think you'd absolutely have to do that. In a scroling scenario, you could create just enough meters (say 10 for 5 contacts in this mini skin code) and measures (15 for the same thing) for the visible part , then dynamically change them on scroll instead of selectively hiding them or whatever. I use similar approaches in my skins to reduce code to a fraction of what it originally would be (example, no other meaning involved: jsmorley's include files for 15 days of weather mean roughly 8000 lines of code for the measures, in just his largest include file; my measures don't even take 1000, and that includes [Variables] and other minor sections). Sure, this works the easier for a single scrolling item, but I have no doubt it can be done for multiple items as well. Basically, it's only the visible part that needs measures/meters in a skin. Dynamically handling things in skins is underrated, IMHO.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth