OnKeyDown event incorrect encoding - gwt

I catch all the character typed while the document is receiving focus using following code:
RootPanel.get().addDomHandler(new KeyDownHandler() {
#Override
public void onKeyDown(KeyDownEvent event) {
char key = (char) event.getNativeKeyCode();
String keyString = String.valueOf(key);
if (!event.isShiftKeyDown())
keyString = keyString.toLowerCase();
System.out.print(keyString);
}
}, KeyDownEvent.getType());
When the device that is sending key events is using ASCII (we cannot control what encoding gets used) then we get the following output:
www¾mitcom¾m3
What can we do so that we get the correctly encoded input in Java?

event.getNativeKeyCode() gives you a key code, which is not a character. From documentation: Gets the key code (code associated with the physical key) associated with this event.. Dot pressed on my keyboard gives me 190. Also to mention in Java char is 16-bit type, while int is 32-bit, i.e. generally (char) integerVal is an unsafe operation.
Now what you probably want to use is event.getNativeEvent().getCharCode(). The problem is that it's always 0 in KeyDownEvent. Therefore, I would suggest to use KeyPressHandler & KeyPressEvent. Your code would look like:
private void onKeyPress(KeyPressEvent event) {
char c = (char) event.getNativeEvent().getCharCode();
String s = String.valueOf(c);
if (event.isShiftKeyDown()) {
s = s.toUpperCase();
}
GWT.log(s);
}
RootPanel.get().addDomHandler(this::onKeyPress, KeyPressEvent.getType());

Related

Nuget.Versioning.SemanticVersion.ToString(format) examples?

I can't seem to find any documentation anywhere on what formats one can pass in to .ToString() on NuGet.Versioning.SemanticVersion. The value seems to be indexing into a list of _formatters but there's no docs on what values are available by default, what the default behavior is, how to tweak it, etc.
e.g. this is all that's in the source code:
//
// Summary:
// Gives a normalized representation of the version. This string is unique to the
// identity of the version and does not contain metadata.
public virtual string ToNormalizedString()
{
return ToString("N", VersionFormatter.Instance);
}
//
// Summary:
// Gives a full representation of the version include metadata. This string is not
// unique to the identity of the version. Other versions that differ on metadata
// will have a different full string representation.
public virtual string ToFullString()
{
return ToString("F", VersionFormatter.Instance);
}
//
// Summary:
// Get the normalized string.
public override string ToString()
{
return ToNormalizedString();
}
//
// Summary:
// Custom string format.
public virtual string ToString(string format, IFormatProvider formatProvider)
{
string formattedString = null;
if (formatProvider == null || !TryFormatter(format, formatProvider, out formattedString))
{
formattedString = ToString();
}
return formattedString;
}
Anybody know where I can find this?
You were so close to finding the list of format characters yourself!
The first two methods you copied into your question reference a property VersionFormatter.Instance. Looking at the VersionFormatter class, the Format method enumerates the list of characters it handles: https://github.com/NuGet/NuGet.Client/blob/08a7a7bd17e504d808329dcc1ffc866d9f59d040/src/NuGet.Core/NuGet.Versioning/VersionFormatter.cs#L65-L101
character
method
N
AppendNormalized(builder, version);
V
AppendVersion(builder, version);
F
AppendFull(builder, version);
R
builder.Append(version.Release);
M
builder.Append(version.Metadata);
x
builder.Append(version.Major);
y
builder.Append(version.Minor);
z
builder.Append(version.Patch);
r
builder.Append(version is NuGetVersion nuGetVersion && nuGetVersion.IsLegacyVersion ? nuGetVersion.Version.Revision : 0);

how can this Repeated string concatenation function

using UnityEngine;
using System.Collections;
public class NewMonoBehaviour1 : MonoBehaviour
{
void ConcatExample(int[] intArray)
{
string line = intArray[0].ToString(); // the line is the var of the first in array
for(i =1;i <intArray.Length; i++) // the length is unknown ?
{
line += ", " + intArray[i].ToString(); //
}
return line;
//each time allocate new in original place
}
}
How can this function work ? the length of array is unknown , so how the for loop works ?Besides, this is void function but shouldn't return anythings right ,or is there any exceptional case ,finally,according to the unity manual, it is said that the function will keep producing a string but with new contents in the same place , resulting in consuming large memory space .Why ?thx
What makes you think that the Length should be unknown? It is a property that any array simply has
Gets the total number of elements in all the dimensions of the Array.
Of course it is not unknown the moment you call your method with an according parameter!
The return line; will not even compile since as you say the method is of type void so it can not return anything. It should probably be private string ConcatExample
Then what the unity manual (don't know where exactly you read this) means lies in
line += ", " + intArray[i].ToString();
under the hood every string in c# is an immutable char[]. So everytime you do a string concatenation via stringC = stringA + stringB what happens under the hood is basically something similar to
char[] stringC = new char[stringA.Length + stringB.Length];
for(var iA = 0; iA < stringA.Length; iA++)
{
stringC[i] = stringA[i];
}
for(var iB = 0; iB < stringB.Length; iB++)
{
stringC[iB + stringA.Length] = stringB[iB];
}
so whenever dealing with loops especially with large data it is strongly recommended to rather use a StringBuilder like
private string ConcatExample(int[] intArray)
{
var builder = new StringBuilder(intArray[0]);
for(i =1; i < intArray.Length; i++)
{
builder.Append(", ").Append(intArray[i].ToString());
}
return builder.ToString();
}
The length of the array will be the length of the array of ints you pass into the function as an argument.
say you pass it
Int[] ints = {1,2,3}
ConcatExample(ints); //the length of the array is now 3
add a debug.log() function to the ConcatExample method
void ConcatExample(int[] intArray)
{
string line = intArray[0].ToString();
for (int i = 1; i < intArray.Length; i++)
{
line += ", " + intArray[i].ToString(); //
Debug.Log(line);
}
}
debug.log would produce the following in the console
1, 2
1, 2, 3
and finally the return line; at the end would just result in an error because yes you are correct void returns nothing
This function CANNOT work, unless it gets the data it expects. A NULL passed to this function, for example, would generate a runtime null-reference exception. Passing a valid integer array, of length zero would generate an invalid index error on the first line.
You are correct, the function returns nothing, and appears pointless. In fact, I would have expected return line; to generate a complier error.
The string type appears "dynamic" meaning, it will indeed allocate more and more memory as needed. Technically, it is actually the string "+" operator, (a function that takes two strings as parameters) that is allocating this space. This function returns a new string, of the appropriate size. The garbage collector will DEallocate "old" strings when they are no longer referenced by any variables.

How to catch *all* characters sent to Text field from a HID barcode scanner?

I need to capture input from a barcode scanner. Up until now the input has been just simple alphanum text which I have captured in one Text field. I added a ModifyListener to the Text field and am able to see the input arrive. That has worked fine.
I now need to handle a more complex matrix code which contains values for multiple fields. The values are separated by non-printable characters such as RS, GS and EOT (0x1E, 0x1D, 0x04). The complete data stream has a well-defined header and an EOT at the end, so I am hoping that I can detect barcode input as opposed to manual input.
When a barcode is detected, I can use the record separators RS to split the message and insert the values into the relevant Text fields.
However, the standard key handler on the Text controls ignore these non-printable characters and they do not appear in the controls text. This makes it impossible to proceed as planned.
How could I modify these Text fields to accept and store all characters? Or is there an alternative approach I could use?
This is the code I used to handle the barcode stream.
public class Main
{
static StringBuilder sb = new StringBuilder();
public static void main(String[] args)
{
Display d = new Display();
Shell shell = new Shell(d);
shell.setLayout(new FillLayout());
Text text = new Text(shell, 0);
text.addListener(SWT.KeyDown, new Listener()
{
#Override
public void handleEvent(Event e)
{
// only accept real characters
if (e.character != 0 && e.keyCode < 0x1000000)
{
sb.append(e.character);
String s = sb.toString();
// have start and end idents in buffer?
int i = s.indexOf("[)>");
if (i > -1)
{
int eot = s.indexOf("\u0004", i);
if (eot > -1)
{
String message = s.substring(i, eot + 1);
handleMessageHere(message);
// get ready for next message
sb = new StringBuilder();
}
}
}
}
});
shell.open();
while (!shell.isDisposed())
{
if (!d.readAndDispatch())
d.sleep();
}
}

GWT numberformat weird behaviour

I have a GWT project for which the locale is set to fr. I have a custom text field that uses a number format to validate and format the numerical inputs.
The formatting works fine but not the input validation. Here is a snapshot of the method that validates that the new value is a valid percentage (this is called onValueChanged):
private void validateNumber(String newVal){
logger.debug("value changed, newVal="+newVal+", current="+current);
// Attempt to parse value
double val=0;
try{
val=Double.parseDouble(newVal);
}catch(NumberFormatException e){
logger.warn("parsing failed",e);
try{
val=getFormatter().parse(newVal);
}catch(NumberFormatException ex){
logger.warn("parsing with nb format failed",ex);
// on failure: restore previous value
setValue(current,false);
return;
}
}
//some check on min and max value here
}
For example if the starting value is set by the program to "0.2" it will show up as 20,00 % hence using the correct decimal separator.
Now:
if I input 0,1 I get a numberformat exception.
if I input 0.1 it show as 10,00 %
if I 10% (without the space before the '%'), I get a numberformat exception
Do you know how I can modify the method to have 0,1 and 10% identified as valid inputs?
As Colin mentioned, you definitely want to parse and format using a GWT Number Format object, not Double, so the parsing and formatting are properly locale specific.
Below is some code snippets I could find to parse, validate and format a percent number.
Note however the edit process has the % unit hard-coded outside of the text box value, hence no conversion between 20,45% and 0.2045 in the edit process, 20,45 is entered directly and visualized as such. I vaguely recall struggling with such conversion during the edit process but forgot the details as it was a while back. So if it is a critical part of your question and requirements then I am afraid the examples below may be of limited value. Anyway, here they are!
Notations:
TextBox txt = new TextBox();
NumberFormat _formatFloat = NumberFormat.getFormat("#,##0.00");
NumberFormat _formatPercent = NumberFormat.getFormat("##0.00%");
Parsing text entry like "20,45" as 20.45 (not "20,45%" as 0.2045):
txt.setText("20,45"); // French locale format example, % symbol hard-coded outside of text box.
try {
float amount = (float) _formatFloat.parse(txt.getText());
} catch (NumberFormatException e) ...
Parsing & Validating text entry like "20,45":
private class PercentEntryValueChangeHandler implements ValueChangeHandler<String>
{
#Override
public void onValueChange(ValueChangeEvent<String> event)
{
validatePercent((TextBox) event.getSource());
}
};
private void validatePercent(final TextBox percentTextBox)
{
try
{
if (!percentTextBox.getText().isEmpty())
{
final float val = (float) _formatFloat.parse(percentTextBox.getText());
if (isValid(val))
percentTextBox.setText(_formatFloat.format(val));
else
{
percentTextBox.setFocus(true);
percentTextBox.setText("");
Window.alert("Please give me a valid value!");
}
}
}
catch (NumberFormatException e)
{
percentTextBox.setFocus(true);
percentTextBox.setText("");
Window.alert("Error: entry is not a valid number!");
}
}
private boolean isValid(float val) { return 12.5 < val && val < 95.5; }
txt.addValueChangeHandler(new PercentEntryValueChangeHandler());
Formatting 20.45 as "20,45":
float val = 20.45;
txt.setText(_formatFloat.format(val));
Formatting 0.2045 as "20,45%" (read only process, the text box is not editable, the % is set inside the text box):
float val = 0.2045;
txt.setText(_formatPercent.format((double)(val))); // * 100 embedded inside format.
It is not fancy and probably far from perfect but it works!
Any feedback on how to improve upon this implementation is more than welcome and appreciated!
I hope it helps anyway.
I managed to make it work by changing the code to the following:
private void validateNumber(String newVal){
double val=0;
try{
val=getFormatter().parse(newVal);
}catch(NumberFormatException e){
boolean ok=false;
try{
val=NumberFormat.getDecimalFormat().parse(newVal);
ok=true;
}catch(NumberFormatException e1){}
if(!ok){
try{
val=Double.parseDouble(newVal);
}catch(NumberFormatException ex){
setValue(current,false);
// inform user
Window.alert(Proto2.errors.myTextField_NAN(newVal));
return;
}
}
}

What is the alternative for String.format() in GWT?

While GWT is not emulate all java's core, what can be used as alternative for:
String.format("The answer is - %d", 42)?
What is the ellegant and efficient pattern to inject arguments to message in GWT?
One elegant solution is using SafeHtml templates. You can define multiple such templates in an interface like:
public interface MyTemplates extends SafeHtmlTemplates {
#Template("The answer is - {0}")
SafeHtml answer(int value);
#Template("...")
...
}
And then use them:
public static final MyTemplates TEMPLATES = GWT.create(MyTemplates.class);
...
Label label = new Label(TEMPLATES.answer(42));
While this is a little bit more work to set up, it has the enormous advantage that arguments are automatically HTML-escaped. For more info, see https://developers.google.com/web-toolkit/doc/latest/DevGuideSecuritySafeHtml
If you want to go one step further, and internationalize your messages, then see also https://developers.google.com/web-toolkit/doc/latest/DevGuideI18nMessages#SafeHtmlMessages
You can simply write your own format function instead of doing brain storm.
public static String format(final String format, final String... args,String delimiter) {
String[] split = format.split(delimiter);//in your case "%d" as delimeter
final StringBuffer buffer= new StringBuffer();
for (int i= 0; i< split.length - 1; i+= 1) {
buffer.append(split[i]);
buffer.append(args[i]);
}
buffer.append(split[split.length - 1]);
return buffer.toString();
}
Because most (as in 99.999%) message formats are static, known at compile-time, the way GWT approaches it is to parse them at compile-time.
You'll generally use a Messages subinterface for its ability to localize the message, but you'll sometimes rather need SafeHtmlTemplates.
In the 0.001% when template is not known at compile time you can use Javascript sprintf (see: http://www.diveintojavascript.com/projects/javascript-sprintf) as in:
public static native String format (String format, JsArrayMixed values) /*-{
return vsprintf(format, values);
}-*/;
You can write your own.
I wrote a version that just work with Strings(%s):
public static String format(final String format, final Object... args)
{
checkNotNull(format);
checkNotNull(args);
final String pattern = "%s";
int start = 0, last = 0, argsIndex = 0;
final StringBuilder result = new StringBuilder();
while ((start = format.indexOf(pattern, last)) != -1)
{
if (args.length <= argsIndex)
{
throw new IllegalArgumentException("There is more replace patterns than arguments!");
}
result.append(format.substring(last, start));
result.append(args[argsIndex++]);
last = start + pattern.length();
}
if (args.length > argsIndex)
{
throw new IllegalArgumentException("There is more arguments than replace patterns!");
}
result.append(format.substring(last));
return result.toString();
}
why not writing a method like:
String appendAnswer(int result) {
return "The answer is - " + Integer.toString(result);
}
is resolving your problem because you do nothing like formatting in your code.
if you ever face the problem like converting integer/byte to Hex String you should use:
Integer.toString(int, 16);
I don't know GWT much but I am working on a GWT project and I needed this. While trying some alternatives, I have found that this is working;
import java.text.MessageFormat;
MessageFormat.format("The answer is - {0}", 42);
I don't know if the project's developers added something special to make this work or it is working by default.