views:

58

answers:

2

Hello! 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.

+1  A: 

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.

High Performance Mark
Having a fixed number format would be great, but it’s not an option, since one of the views is the plain four-function calculator that has to behave exactly as the simple button calculators do. Could you be more specific about the separation idea? Can’t see where are you going.
zoul
A: 

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.

zoul