Have problems designing input and output for a calculator app - model-view-controller

I am writing a button calculator. I have the code split into model, view and a controller. The model knows nothing about formatting, it is only concerned with numbers. All formatting is done in the view. The model gets its input as keypresses, each keypress is a part of an enum:
typedef enum {
kButtonUnknown = 0,
kButtonMemoryClear = 100,
kButtonMemoryPlus = 112,
kButtonMemoryMinus = 109,
kButtonMemoryRecall = 114,
kButtonClear = 99,
…
};
When the user presses a button (say 1), the model receives a button code (kButtonNum1), adds the corresponding number to a string input buffer ("1") and updates the numeric output value (1.0). The controller then passes the numeric output value to the view that formats it (1).
This is all plain, simple and clean, but does not really work. The problem is that when user enters a part of a number (say 0.00, going to enter 0.001), the input does not survive the way through model to view and the display says 0 instead of 0.00. I know why this happens ("0.00"::string parses to 0::double and that gets formatted as 0). What I don’t know is how to design the calculator so that the code stays clean and simple and the numbers will show up on screen exactly as the user types them.
I’ve already come with some kind of solution, but that’s essentially a hack and breaks the beautiful and simple flow from the calculator model to the display.
Ideas?
Current solution keeps track of the calculator state. If the calculator is building a number, I take the calculator input buffer (a string) and directly set the display contents (also a string). Otherwise I take the proper path, ie. take the numeric calculator output, pass it to the view as a double and the view uses its internal formatter to create a string for the display. Example input:
input | display | mode
------+---------+------------
0 | 0 | from string
0. | 0. | from string
0.0 | 0.0 | from string
0.0+ | 0 | from number
This is ugly. (1) The calculator has to expose its input buffer and state. (2) The view has to expose its display and allow setting its contents directly using a string. (3) I have to duplicate some of the formatting code to format the string I got from the calculator input buffer. If user enters 12345.000, I have to display 12,345.000 and therefore I’ve got to have a commification code for strings. Yuck.

On my calculator (HP48SX) the numbers in the display are formatted according to the settings for displaying numbers. Right now, if I enter 0.00 (or any variant thereof) it is displayed as 0.0000. Perhaps you could separate display (ie formatting) from internal number representation ? In terms of MVC I guess that this would be implemented as state in the C.
EDIT in response to OP's comment. I don't fully understand the limitations of what you call a button calculator so you're on your own there. As for separation, I would design the calculator such that:
Model is always working with whatever you use for representing numbers: floats, doubles, decimals, what-have-you.
View is always working with strings which present numbers nicely and allow users to enter as they wish.
Controller translates from string to number, from number to string. In my original suggestion I envisaged that Controller itself would be stateful (storing current-numeric-format for example) and be addressable from the buttons. But you seem to have ruled that out.
Your problem, as I see it, is that if you don't store this state somewhere then you have no way of telling the calculator to use anything other than a fixed* format for displaying any number entered. By fixed* I mean a very limited form of flexibility, such as always displaying the number of decimal digits that were in the most recently entered number, rather than absolutely fixed such as 12 digits, no more and no less.

At last I’ve found a nicer solution. I have added an inputHint property to the formatter object that takes care of the output formatting in the view. This input hint receives the value of the calculator input buffer and affects the formatting. If there is a decimal dot in the input hint, the formatter is forced to always keep the decimal dot in output, therefore solving the case of "0." being formatted as "0". And if the input contains some fraction digits, the formatter is forced to keep the same number of fraction digits in output (solves the case of "0.00" being formatted as "0").
I still have to expose the calculator input buffer and state, but I don’t have to expose the view’s display as string and don’t have to maintain the duplicate formatting code path for strings.

Related

How to set entry filter for 24 hour time format in the listbox column in 4d database

I have a listbox with 2 columns (say "from time" and "to time"). I want to filter user input by 24 hour format only i.e. no other key should be allowed to press except 24 hour time format (i.e 00:00 to 24:00) in the cell. I tried with this: &"0-2"#&"0-3"#:& "0-5"#&"0-9"# it works well but it didn't allow to put something 19:22 or the value after 13:59 in the cell value as I haven't passed other optional value for that 24 hour time format. In regex, it's a bit easy to achieve this ('/^([01][0-9]|2[0-3]):([0-5][0-9])$/') but not sure how this can be done in the 4d database listbox cell field.
Any help would be appreciated. Thanks.
I suggest you make the list box columns text and manage the display and UI yourself if you require fine control over the input values.
The Time string method will convert a time value for you:
$timeStr:=Time string(Current time) // $timeStr = "07:23:45"
The input filters are not RegEx and will not give you the kind of fine control you need. They will let you filter unwanted characters (anything besides numbers for instance). Try this for the Entry Filter on the column
!0&9##:##:##
The result will be a text string of the numbers entered. Write a method to take the input string, parse the elements, validate them, update the data source and then return a properly formatted string for display. I would use the On data change form event as the trigger for running the method.
$h:=Num(Substring($inputStr;1;2))
$m:=Num(Substring($inputStr;3;2))
$s:=Num(Substring($inputStr;5;2))
Recent versions of 4D manage time values as seconds since midnight which is why you may get a longint value instead of a 'time' value sometimes. And depending on which version you are using and the type of listbox (collection, entity selection, array, etc.) you may not even have a 'time' type option for the list box column which can be confusing. Given all that it's just easier to stringify the value and work with that.
For example, what do you want to do if a user enters "33:45:00"? If you want to reject the "33" at the outset you can do this by evaluating each character as it is typed. The On After Keystroke form event lets you run your evaluation method after each change in the field and the Get edited text command allows you to see what the user is entering. https://doc.4d.com/4Dv18R3/4D/18-R3/Get-edited-text.301-4901376.en.html
To convert a string (or longint) into a time value use the Time method:
$timeVar:=Time($timeStr)
4D is a typed language and has had a time type since the beginning. However with the addition of ORDA some UI objects no longer support the time type (collection and entity selection list boxes, for example) and use a longint type instead. This can be confusing if you are working with an existing app or older code but attempting to use the newer tools. Be sure to look over
https://developer.4d.com/docs/en/Concepts/time.html
and
https://doc.4d.com/4Dv18/4D/18/Date-and-Time.201-4504355.en.html
You may not need to get so involved in the input. It depends on the nature of the UI and the data. Time and date is tricky in just about every platform.

Convert to E164 only if possible?

Can I determine if the user entered a phone number that can be safely formatted into E164?
For Germany, this requires that the user started his entry with a local area code. For example, 123456 may be a subscriber number in his city, but it cannot be formatted into E164, because we don't know his local area code. Then I would like to keep the entry as it is. In contrast, the input 089123456 is independent of the area code and could be formatted into E164, because we know he's from Germany and we could convert this into +4989123456.
You can simply convert your number into E164 using libphonenumber
and after conversion checks if both the strings are same or not. If they're same means a number can not be formatted, otherwise the number you'll get from library will be formatted in E164.
Here's how you can convert
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
String formattedNumber = phoneUtil.format(inputNumber, PhoneNumberFormat.E164);
Finally compare formattedNumber with inputNumber
It looks as though you'll need to play with isValidNumber and isPossibleNumber for your case. format is certainly not guaranteed to give you something actually dialable, see the javadocs. This is suggested by the demo as well, where formatting is not displayed when isValidNumber is false.
I also am dealing with this FWIW. In the context of US numbers: The issue is I'd like to parse using isPossibleNumber in order to be as lenient as possible, and store the number in E164. However then we accept, e.g. +15551212. This string itself even passes isPossibleNumber despite clearly (I think) not being dialable anywhere.

Telerik MVC CurrencyTextBox - Custom value formatting

(First off, I have already posted this on the Telerik forums (link), but this site gets more traffic, so I'm hoping to get some help sooner.)
I am trying to achieve some custom value formatting with the CurrencyTextBox, but the way that the control handles values is making things decidedly hard.
What I want to do is this: if the user enters a value that does not contain a "." character, it will format that value as cents instead of dollars. So if a user enters "16", I want the control to display (and contain a value of) $0.16. If the user enters a value with a ".", I would like the control to function as normal. If the user enters "16.", "16.0" or "16.00", I want the control to display (and contain a value of) "$16.00". This application will be used by people in the retail business and this is how they expect inputs for price values to function.
However, whether I subscribe to the OnChange event or even the "blur" event on the textbox itself, it is stripping the "." character if there is either nothing after it or only 0's after it. Example: If I enter in a value of "16.", "16.0" or "16.00", the value pulled from the textbox in javascript will be "16". And since I have to check for the presence of the "." character, this breaks my logic to properly format the value.
So I'm looking for some help or suggestions. Here is the javascript that I have right now to properly format the value as required. As you can see, if the value does not contain a "." character, the value is divided by 100, which is exactly what I want. Stripping this character is killing my logic. :)
$('custom-price').find('input').live('blur', function (e) {
var sender = $(this).data('tTextBox');
var priceVal = $(this).val(); // $(this).attr('value') also returns the value with the character stripped, FYI
if (priceVal.indexOf(".") == -1) {
priceVal = priceVal / 100;
}
sender.value(priceVal);
});
Try the same using ascii code for "." operator (46). OnKeyPress if you find ascii code 46 change the format for control..
Regards,
Dhaval Shukla

Keep input from evaluating in a pop-up box?

I have the following mma code:
$ButtonOptions = {Method -> "Queued"};
Button["Get List of IDs",
ai = ToString#Input["Please Enter ID#s", {}];
ai = StringReplace["ai", "\[Times]" -> ","];
Print#ai,
Background -> Yellow, Sequence ## $ButtonOptions
]
I need users to input multiple ID numbers in those brackets when the input window pops up. They like to use Excel and paste in a column, but this results in a new paragraph for each ID number (which Mathematica converts to a space, and then to multiplication, and then it multiplies all the IDs together). I need some way to keep the input from evaluating when they enter it without having Hold actually show up in the input box so the StringReplace operation will work and get rid of all the line breaks before Mathematica multiplies the IDs together.
How about something using InputString?
Button["Get List of IDs",
ai = InputString["Please Enter ID#s", {}];
ai = DeleteCases[StringSplit[ai, WhitespaceCharacter | ","], ""];
Print[ai],
Method -> "Queued"]
Of course, you probably want to have more checks on the types of Ids. In the above code I used StringSplit to separate the string at spaces, tabs, newlines and commas - but this is probably a bit too simplistic and not robust enough for real life use.

Java applet - Real-time textfield input verification

I'm trying to develop an input real-time verification on a textfield in a Java applet.
The idea would be to have an input field that, if empty, once the user clicks in it it would show something like "0,00". Once the user starts to press the keys, only numbers should be accepted, and it would start to fill the text like this (imagine I input the numbers:
1,2,3,4,5,6):
"0,01" -> "0,12" -> "1,23" -> "12,34" -> "123,45" -> "1.234,56".
If the field is not empty the user can change the values but there will always be a "," dividing the decimal numbers.
I've been able to allow only numbers to be accepted but how can produce this kind of behavior? I know this may be a very specific question but any links or examples would be much appreciated. Thank you.
You will have to provide an input handler, that not only filters the input, but also calls a preset callback (made by you), that will update the required field in the way you want it to be updated.
You can use some functions, that can format numbers, given a specific format.
Basically, just keep a count on number of digits, already input, then parse it as a plain integer then multiply it by a power of 10, derived from the format, in your example would be something like 10 raised to the power of (numberOfInputDigits -2).

Resources