The BWidget ComboBox widget allows you to fill in an entry field with a value. I would like to enforce only specific characters in that field (e.g. only [a-z0-9]). For that purpose I would like to use Tcl/Tk's -validatecommand (or -vcmd for short), just as you do with the standard 'entry' widget:
proc ValidateMyEntry { value } {
# Check if it's alphanum string
if ![regexp {^[-a-zA-Z0-9]*$} $value] {
return 0
}
return 1
}
entry .my_entry -width 20 -textvariable myVar -validate key -vcmd {ValidateMyEntry %P}
It seems ComboBox does not support -validatecommand. What's the best work-around?
If you want to use a BWidget, you can try with -modifycmd or -postcommand.
Anyway I would suggest you to try the ttk::combobox with the -postcommand option.
As something that was possible but a bit cumbersome, I decided to use the old-style 'trace variable' function to enforce values in combobox.
Put the following statement after the ComboBox call:
trace variable myVar w forceAlphaNum
Elsewhere, you have to define the forceAlphaNum proc:
proc forceAlphaNum { name el op } {
if { $el == "" } {
set newname $name
set oldname ${name}_alphanum
} else {
set newname ${name}($el)
set oldname ${name}_alphanum($el)
}
global $newname
global $oldname
if { ![info exist $oldname] } {
set $oldname ""
}
# Check if it's alphanum string
if ![regexp {^[a-zA-Z0-9]*$} [set $newname]] {
set $newname [set $oldname]
bell; return
}
set $oldname [set $newname]
}
Related
You know how in C and JavaScript variable assignments can take place within conditions, such as
if ( boolean || (val = func(args)) == case1 ) {
/* Perform A */
} else if ( val == case2) {
/* Perform B */
} ...
such that don't need to write another elseif to perform code A.
Can this be done in Tcl; and, if so, how?
It's not very important but I'd like to know just the same.
Thank you.
You can use set and other commands in an expr-ression, and set returns the newly assigned value, so...
set boolean true
proc func {} { return case2 }
if {$boolean && [set val [func]] eq "case1"} {
puts "case 1 found"
} elseif {$val eq "case2"} {
puts "case 2 found"
}
I was assuming that "return" in PowerShell function will return the value and exit the function, but instead of that I am getting the values for two times!!!!???
Please assist me.
I have a default value, I have logic for retreiving the real value (if exists) but instead I am getting two fules as output - but I do not want that! I need just one value.
Thank you in advance!!!
function GetTenantTagValue($TAG_SET_NAME) {
Write-Host("Tag Set Name:"+$TAG_SET_NAME)
$TAG_SET_VALUE = "N/A"
$TENANT_TAGS = "Customer Code/HEDGE"
$TENANT_TAGS | ForEach-Object {
$TAG_NAME = $_.split("/")[0]
$TAG_VALUE = $_.split("/")[1]
if ($TAG_NAME -eq $TAG_SET_NAME) {
# $TAG_SET_VALUE = $TAG_VALUE
Write-Host("Tag Value:"+$TAG_VALUE)
Write-Host("#########################")
return $TAG_VALUE
}
}
Write-Host("Tag Set Value:"+$TAG_SET_VALUE)
return $TAG_SET_VALUE
}
I invoke the function with:
GetTenantTagValue "Customer Code"
function ExtractLocations([ref]$lp_Locations) {
$lp_Locations.Value = "A STRING VALUE"
return 0
}
...
$Locations = ""
if (#(ExtractLocations([ref]$Locations)) -ne 0) {
RecordErrorThenExit
}
$Locations always ends up as a blank string.
Apart from what #mklemen0 said, to set the value, you need not to do it like $Variable.Value = 'Something' , its just $Variable = 'Something'
With the #() expression, you are converting the output to an array which is not what you need here. Declaring functions similar to methods in c# is not suggested in PowerShell. You could do it like below.
function ExtractLocations{
Param([ref]$lp_Locations)
$lp_Locations = "A STRING VALUE"
return 0
}
ExtractLocations -lp_Locations ([ref]$Locations)
Could not get it working with parameters no matter what I tried so returned the value as a string and that works:
function ExtractLocations
{
....
return $lp_Locations
}
$Locations = ExtractLocations
write "MODIFY $TABLE TO REORGANIZE WITH LOCATION = ($($Locations.value)) \p\g" | sql $SQLFLAGS $TARGETDB
I am trying to define the local variables and assign to them as below :
#defining((Json.parse(value), ("GGGGGG"))) {case (json:JsValue, lb)=>
#{lb=json\\"myTestField"}
}
but getting the error reassignment to val. So I tried to declare lb as var like
#defining((Json.parse(value), ("GGGGGG"))) {case (json:JsValue, lb:var)=>
#{lb=json\\"myTestField"}
}
but getting the error identifier expected but 'var' found
How can I assign to variable lb?
Here is how you can assign to a val and use it further down in your view. What you are doing should really be done in the controller.
#someValue = #{
//your logic to assign to someValue
}
//pass value to another view
#anotherView(someValue)
Edit as per comment below:
#Json.parse(value) match {
case Some(value) if value == "GGGGGG" => {
<div>#value</div>
}
case _ => {
<div>some default value</div>
}
}
You cannot assign anything else to lb since lb is a val. Pattern matching is working in this way and it is done on purpose.
I have a class that has several inner values:
private variable layer_type
private variable color
private variable name
private variable thickness
private variable conductivity
private variable permittivity
private variable loss_tangent
I want to initiate them with values that the user gives to the constructor, but since there 7 of them, to reduce clutter and code size I did it in a loop:
constructor {in_layer_type in_color in_conductivity in_loss_tangent in_name in_permittivity in_thikness f_row frame} {
foreach var [list layer_type color conductivity loss_tangent name permittivity thikness] {
set $var [set in_$var]
}
Is there any difference (performance wise) with this approach, over the writing all the set commands?
set layer_type $in_layer_type
set color $in_color
#...
set thickness $in_thickness
In strict terms of efficiency, writing it all out in full is the most efficient method. I suggest that you don't do that! The problem is that it's difficult to maintain and hard to use (I don't know about you, but I hate calls with lots of mandatory positional arguments in all languages!) Instead, try something like this:
constructor {f_row frame args} {
foreach {var value} $args {
if {[string match -* $var]} {
set [string range $var 1 end] $value
}
}
# ...
}
Yes, you need to write things a bit different to use this:
TheClass theObjToMake $theFRow $theFrame -layer_type 12345 ...
You're also advised to use Itcl's facilities for setting defaults if you're doing this. Pick something sensible and it will all suddenly seem very natural.