[haiku-commits] r36402 - haiku/trunk/src/apps/deskcalc

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 21 Apr 2010 19:20:29 +0200 (CEST)

Author: stippi
Date: 2010-04-21 19:20:29 +0200 (Wed, 21 Apr 2010)
New Revision: 36402
Changeset: http://dev.haiku-os.org/changeset/36402/haiku
Ticket: http://dev.haiku-os.org/ticket/5203

Modified:
   haiku/trunk/src/apps/deskcalc/CalcView.cpp
   haiku/trunk/src/apps/deskcalc/ExpressionTextView.cpp
   haiku/trunk/src/apps/deskcalc/ExpressionTextView.h
Log:
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.


Modified: haiku/trunk/src/apps/deskcalc/CalcView.cpp
===================================================================
--- haiku/trunk/src/apps/deskcalc/CalcView.cpp  2010-04-21 16:46:32 UTC (rev 
36401)
+++ haiku/trunk/src/apps/deskcalc/CalcView.cpp  2010-04-21 17:20:29 UTC (rev 
36402)
@@ -917,7 +917,7 @@
        }
 
        // render new result to display
-       fExpressionTextView->SetExpression(value.String());
+       fExpressionTextView->SetValue(value.String());
 }
 
 

Modified: haiku/trunk/src/apps/deskcalc/ExpressionTextView.cpp
===================================================================
--- haiku/trunk/src/apps/deskcalc/ExpressionTextView.cpp        2010-04-21 
16:46:32 UTC (rev 36401)
+++ haiku/trunk/src/apps/deskcalc/ExpressionTextView.cpp        2010-04-21 
17:20:29 UTC (rev 36402)
@@ -30,7 +30,9 @@
        fKeypadLabels(""),
        fPreviousExpressions(20),
        fHistoryPos(0),
-       fCurrentExpression("")
+       fCurrentExpression(""),
+       fCurrentValue(""),
+       fChangesApplied(false)
 {
        SetStylable(false);
        SetDoesUndo(true);
@@ -64,7 +66,7 @@
 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 @@
        }
        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 @@
 }
 
 
+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 @@
        AddExpressionToHistory(Text());
        fCalcView->FlashKey("=", 1);
        fCalcView->Evaluate();
+       fChangesApplied = true;
 }
 
 
@@ -156,6 +178,145 @@
 
 
 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()
 {
        const char bytes[1] = { B_BACKSPACE };

Modified: haiku/trunk/src/apps/deskcalc/ExpressionTextView.h
===================================================================
--- haiku/trunk/src/apps/deskcalc/ExpressionTextView.h  2010-04-21 16:46:32 UTC 
(rev 36401)
+++ haiku/trunk/src/apps/deskcalc/ExpressionTextView.h  2010-04-21 17:20:29 UTC 
(rev 36402)
@@ -32,6 +32,7 @@
        virtual void                            GetDragParameters(BMessage* 
dragMessage,
                                                                        
BBitmap** bitmap, BPoint* point,
                                                                        
BHandler** handler);
+                       void                            SetTextRect(BRect rect);
 
        // InputTextView
        virtual void                            RevertChanges();
@@ -41,6 +42,7 @@
                        void                            AddKeypadLabel(const 
char* label);
 
                        void                            SetExpression(const 
char* expression);
+                       void                            SetValue(const char* 
value);
 
                        void                            BackSpace();
                        void                            Clear();
@@ -59,6 +61,9 @@
                        BList                           fPreviousExpressions;
                        int32                           fHistoryPos;
                        BString                         fCurrentExpression;
+                       BString                         fCurrentValue;
+                       
+                       bool                            fChangesApplied;
 };
 
 #endif // EXPRESSION_TEXT_VIEW_H


Other related posts: