Patch by Wim: The resulting expression string is now fit to the current width
of the window. Insignificant digits are truncated from the end. DeskCalc may also switch to scientific notation if there is not enough room left. Thanks a lot! Fixes ticket #5203. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36402 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d7fcb36f2b
commit
665c794f1d
|
@ -917,7 +917,7 @@ CalcView::Evaluate()
|
|||
}
|
||||
|
||||
// render new result to display
|
||||
fExpressionTextView->SetExpression(value.String());
|
||||
fExpressionTextView->SetValue(value.String());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ ExpressionTextView::ExpressionTextView(BRect frame, CalcView* calcView)
|
|||
fKeypadLabels(""),
|
||||
fPreviousExpressions(20),
|
||||
fHistoryPos(0),
|
||||
fCurrentExpression("")
|
||||
fCurrentExpression(""),
|
||||
fCurrentValue(""),
|
||||
fChangesApplied(false)
|
||||
{
|
||||
SetStylable(false);
|
||||
SetDoesUndo(true);
|
||||
|
@ -64,7 +66,7 @@ ExpressionTextView::MakeFocus(bool focused)
|
|||
void
|
||||
ExpressionTextView::KeyDown(const char* bytes, int32 numBytes)
|
||||
{
|
||||
// handle expression history
|
||||
// Handle expression history
|
||||
if (bytes[0] == B_UP_ARROW) {
|
||||
PreviousExpression();
|
||||
return;
|
||||
|
@ -75,22 +77,30 @@ ExpressionTextView::KeyDown(const char* bytes, int32 numBytes)
|
|||
}
|
||||
BString current = Text();
|
||||
|
||||
// handle in InputTextView, except B_TAB
|
||||
// Handle in InputTextView, except B_TAB
|
||||
if (bytes[0] == '=')
|
||||
ApplyChanges();
|
||||
else if (bytes[0] != B_TAB)
|
||||
InputTextView::KeyDown(bytes, numBytes);
|
||||
|
||||
// pass on to CalcView if this was a label on a key
|
||||
// Pass on to CalcView if this was a label on a key
|
||||
if (fKeypadLabels.FindFirst(bytes[0]) >= 0)
|
||||
fCalcView->FlashKey(bytes, numBytes);
|
||||
else if (bytes[0] == B_BACKSPACE)
|
||||
fCalcView->FlashKey("BS", 2);
|
||||
|
||||
// as soon as something is typed, we are at the
|
||||
// end of the expression history
|
||||
// As soon as something is typed, we are at the end of the expression
|
||||
// history.
|
||||
if (current != Text())
|
||||
fHistoryPos = fPreviousExpressions.CountItems();
|
||||
|
||||
// If changes where not applied the value has become a new expression
|
||||
// note that even if only the left or right arrow keys are pressed the
|
||||
// fCurrentValue string will be cleared.
|
||||
if (!fChangesApplied)
|
||||
fCurrentValue.SetTo("");
|
||||
else
|
||||
fChangesApplied = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -117,6 +127,17 @@ ExpressionTextView::GetDragParameters(BMessage* dragMessage,
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::SetTextRect(BRect rect)
|
||||
{
|
||||
InputTextView::SetTextRect(rect);
|
||||
|
||||
int32 count = fPreviousExpressions.CountItems();
|
||||
if (fHistoryPos == count && fCurrentValue.CountChars() > 0)
|
||||
SetValue(fCurrentValue.String());
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
@ -133,6 +154,7 @@ ExpressionTextView::ApplyChanges()
|
|||
AddExpressionToHistory(Text());
|
||||
fCalcView->FlashKey("=", 1);
|
||||
fCalcView->Evaluate();
|
||||
fChangesApplied = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -155,6 +177,145 @@ ExpressionTextView::SetExpression(const char* expression)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::SetValue(const char* value)
|
||||
{
|
||||
// copy the value string so we can modify it
|
||||
BString val(value);
|
||||
|
||||
// save the value
|
||||
fCurrentValue = val;
|
||||
|
||||
// calculate the width of the string
|
||||
BFont font;
|
||||
uint32 mode = B_FONT_ALL;
|
||||
GetFontAndColor(&font, &mode);
|
||||
float stringWidth = font.StringWidth(val);
|
||||
|
||||
// make the string shorter if it does not fit in the view
|
||||
float viewWidth = Frame().Width();
|
||||
if (val.CountChars() > 3 && stringWidth > viewWidth) {
|
||||
|
||||
// get the position of the first digit
|
||||
int32 firstDigit = 0;
|
||||
if (val[0] == '-')
|
||||
firstDigit++;
|
||||
|
||||
// calculate the value of the exponent
|
||||
int32 exponent = 0;
|
||||
int32 offset = val.FindFirst('.');
|
||||
if (offset == B_ERROR) {
|
||||
exponent = val.CountChars() - 1 - firstDigit;
|
||||
val.Insert('.', 1, firstDigit + 1);
|
||||
} else {
|
||||
if (offset == firstDigit + 1) {
|
||||
// if the value is 0.01 or larger then scientific notation
|
||||
// won't shorten the string
|
||||
if (val[firstDigit] != '0' || val[firstDigit+2] != '0'
|
||||
|| val[firstDigit+3] != '0') {
|
||||
exponent = 0;
|
||||
} else {
|
||||
// remove the period
|
||||
val.Remove(offset, 1);
|
||||
|
||||
// check for negative exponent value
|
||||
exponent = 0;
|
||||
while (val[firstDigit] == '0') {
|
||||
val.Remove(firstDigit, 1);
|
||||
exponent--;
|
||||
}
|
||||
|
||||
//add the period
|
||||
val.Insert('.', 1, firstDigit + 1);
|
||||
}
|
||||
} else {
|
||||
// if the period + 1 digit fits in the view scientific notation
|
||||
// won't shorten the string
|
||||
BString temp = val;
|
||||
temp.Truncate(offset + 2);
|
||||
stringWidth = font.StringWidth(temp);
|
||||
if (stringWidth < viewWidth)
|
||||
exponent = 0;
|
||||
else {
|
||||
// move the period
|
||||
val.Remove(offset, 1);
|
||||
val.Insert('.', 1, firstDigit + 1);
|
||||
|
||||
exponent = offset - (firstDigit + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the exponent
|
||||
offset = val.CountChars() - 1;
|
||||
if (exponent != 0)
|
||||
val << "E" << exponent;
|
||||
|
||||
// reduce the number of digits until the string fits or can not be
|
||||
// made any shorter
|
||||
stringWidth = font.StringWidth(val);
|
||||
char lastRemovedDigit = '0';
|
||||
while (offset > firstDigit && stringWidth > viewWidth) {
|
||||
if (val[offset] != '.')
|
||||
lastRemovedDigit = val[offset];
|
||||
val.Remove(offset--, 1);
|
||||
stringWidth = font.StringWidth(val);
|
||||
}
|
||||
|
||||
// there is no need to keep the period if no digits follow
|
||||
if (val[offset] == '.') {
|
||||
val.Remove(offset, 1);
|
||||
offset--;
|
||||
}
|
||||
|
||||
// take care of proper rounding of the result
|
||||
int digit = (int)lastRemovedDigit - 48; // ascii to int
|
||||
if (digit >= 5) {
|
||||
for (; offset >= firstDigit; offset--) {
|
||||
if (val[offset] == '.')
|
||||
continue;
|
||||
digit = (int)(val[offset]) - 47; // ascii to int + 1
|
||||
if (digit != 10) break;
|
||||
val.Remove(offset, 1);
|
||||
}
|
||||
if (digit == 10) {
|
||||
// carry over, shift the result
|
||||
if (val[firstDigit+1] == '.') {
|
||||
val[firstDigit+1] = '0';
|
||||
val[firstDigit] = '.';
|
||||
}
|
||||
val.Insert('1', 1, firstDigit);
|
||||
|
||||
//remove the exponent value and the last digit
|
||||
offset = val.FindFirst('E');
|
||||
if (offset == B_ERROR)
|
||||
offset = val.CountChars();
|
||||
val.Truncate(--offset);
|
||||
offset--; //offset now points to the last digit
|
||||
|
||||
// increase the exponent and add it back to the string
|
||||
exponent++;
|
||||
val << 'E' << exponent;
|
||||
} else {
|
||||
// increase the current digit value with one
|
||||
val[offset] = char(digit + 48);
|
||||
}
|
||||
}
|
||||
|
||||
// remove trailing zeros
|
||||
while (val[offset] == '0')
|
||||
val.Remove(offset--, 1);
|
||||
|
||||
// there is no need to keep the period if no digits follow
|
||||
if (val[offset] == '.')
|
||||
val.Remove(offset, 1);
|
||||
}
|
||||
|
||||
// set the new value
|
||||
SetExpression(val);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::BackSpace()
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ class ExpressionTextView : public InputTextView {
|
|||
virtual void GetDragParameters(BMessage* dragMessage,
|
||||
BBitmap** bitmap, BPoint* point,
|
||||
BHandler** handler);
|
||||
void SetTextRect(BRect rect);
|
||||
|
||||
// InputTextView
|
||||
virtual void RevertChanges();
|
||||
|
@ -41,6 +42,7 @@ class ExpressionTextView : public InputTextView {
|
|||
void AddKeypadLabel(const char* label);
|
||||
|
||||
void SetExpression(const char* expression);
|
||||
void SetValue(const char* value);
|
||||
|
||||
void BackSpace();
|
||||
void Clear();
|
||||
|
@ -59,6 +61,9 @@ class ExpressionTextView : public InputTextView {
|
|||
BList fPreviousExpressions;
|
||||
int32 fHistoryPos;
|
||||
BString fCurrentExpression;
|
||||
BString fCurrentValue;
|
||||
|
||||
bool fChangesApplied;
|
||||
};
|
||||
|
||||
#endif // EXPRESSION_TEXT_VIEW_H
|
||||
|
|
Loading…
Reference in New Issue