[haiku-commits] haiku: hrev44442 - src/apps/deskcalc src/kits/shared headers/private/shared

  • From: jscipione@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 31 Jul 2012 06:42:34 +0200 (CEST)

hrev44442 adds 1 changeset to branch 'master'
old head: 93aac98d0a9b8ce27f94eb449cfc742446a50274
new head: 8ffd0477dd4998324e051800da35cadd91a7fb8c

----------------------------------------------------------------------------

8ffd047: Implement degree mode in DeskCalc.
  
  Default is radian mode,  You set the option in the right click menu
  like the other options.
  
  Note: degree mode does not affect hyperbolic trigonometric functions.
  This is how Mac Calculator, Windows Calculator, and Google Calculator
  work.

                                     [ John Scipione <jscipione@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev44442
Commit:      8ffd0477dd4998324e051800da35cadd91a7fb8c
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8ffd047
Author:      John Scipione <jscipione@xxxxxxxxx>
Date:        Tue Jul 31 02:35:57 2012 UTC

----------------------------------------------------------------------------

7 files changed, 98 insertions(+), 3 deletions(-)
headers/private/shared/ExpressionParser.h |    6 ++-
src/apps/deskcalc/CalcOptions.cpp         |    8 +++-
src/apps/deskcalc/CalcOptions.h           |    1 +
src/apps/deskcalc/CalcView.cpp            |   24 ++++++++++++
src/apps/deskcalc/CalcView.h              |    8 ++++
src/apps/deskcalc/CalcWindow.cpp          |    4 ++
src/kits/shared/ExpressionParser.cpp      |   50 ++++++++++++++++++++++++-

----------------------------------------------------------------------------

diff --git a/headers/private/shared/ExpressionParser.h 
b/headers/private/shared/ExpressionParser.h
index 9c835b3..4778b29 100644
--- a/headers/private/shared/ExpressionParser.h
+++ b/headers/private/shared/ExpressionParser.h
@@ -42,6 +42,9 @@ class ExpressionParser {
                                                                
ExpressionParser();
                                                                
~ExpressionParser();
 
+                       bool                            DegreeMode();
+                       void                            SetDegreeMode(bool 
degrees);
+
                        void                            SetSupportHexInput(bool 
enabled);
 
                        BString                         Evaluate(const char* 
expressionString);
@@ -49,7 +52,6 @@ class ExpressionParser {
                        double                          EvaluateToDouble(const 
char* expressionString);
 
  private:
-
                        MAPM                            _ParseBinary();
                        MAPM                            _ParseSum();
                        MAPM                            _ParseProduct();
@@ -64,6 +66,8 @@ class ExpressionParser {
                        void                            _EatToken(int32 type);
 
                        Tokenizer*                      fTokenizer;
+
+                       bool                            fDegreeMode;
 };
 
 #endif // EXPRESSION_PARSER_H
diff --git a/src/apps/deskcalc/CalcOptions.cpp 
b/src/apps/deskcalc/CalcOptions.cpp
index b737f4d..3b35379 100644
--- a/src/apps/deskcalc/CalcOptions.cpp
+++ b/src/apps/deskcalc/CalcOptions.cpp
@@ -20,6 +20,7 @@ CalcOptions::CalcOptions()
        :
        auto_num_lock(false),
        audio_feedback(false),
+       degree_mode(false),
        keypad_mode(KEYPAD_MODE_BASIC)
 {
 }
@@ -37,6 +38,9 @@ CalcOptions::LoadSettings(const BMessage* archive)
        if (archive->FindBool("audio feedback", &option) == B_OK)
                audio_feedback = option;
 
+       if (archive->FindBool("degree mode", &option) == B_OK)
+               degree_mode = option;
+
        if (archive->FindUInt8("keypad mode", &keypad_mode_option) == B_OK)
                keypad_mode = keypad_mode_option;
 }
@@ -51,8 +55,10 @@ CalcOptions::SaveSettings(BMessage* archive) const
                ret = archive->AddBool("audio feedback", audio_feedback);
 
        if (ret == B_OK)
+               ret = archive->AddBool("degree mode", degree_mode);
+
+       if (ret == B_OK)
                ret = archive->AddUInt8("keypad mode", keypad_mode);
 
        return ret;
 }
-
diff --git a/src/apps/deskcalc/CalcOptions.h b/src/apps/deskcalc/CalcOptions.h
index 1eb013d..2fb45a0 100644
--- a/src/apps/deskcalc/CalcOptions.h
+++ b/src/apps/deskcalc/CalcOptions.h
@@ -24,6 +24,7 @@ class BMessage;
 struct CalcOptions {
        bool auto_num_lock;             // automatically activate numlock
        bool audio_feedback;    // provide audio feedback
+       bool degree_mode;               // radian or degree mode
        uint8 keypad_mode;              // keypad mode options
 
                                CalcOptions();
diff --git a/src/apps/deskcalc/CalcView.cpp b/src/apps/deskcalc/CalcView.cpp
index bab5c92..eba3f4f 100644
--- a/src/apps/deskcalc/CalcView.cpp
+++ b/src/apps/deskcalc/CalcView.cpp
@@ -244,6 +244,10 @@ CalcView::MessageReceived(BMessage* message)
                        case MSG_OPTIONS_AUDIO_FEEDBACK:
                                ToggleAudioFeedback();
                                return;
+
+                       case MSG_OPTIONS_ANGLE_MODE:
+                               ToggleAngleMode();
+                               return;
                }
        }
 
@@ -931,6 +935,7 @@ CalcView::Evaluate()
 
        try {
                ExpressionParser parser;
+               parser.SetDegreeMode(fOptions->degree_mode);
                value = parser.Evaluate(expression.String());
        } catch (ParseException e) {
                BString error(e.message.String());
@@ -970,6 +975,16 @@ CalcView::ToggleAudioFeedback(void)
        fAudioFeedbackItem->SetMarked(fOptions->audio_feedback);
 }
 
+
+void
+CalcView::ToggleAngleMode(void)
+{
+       fOptions->degree_mode = !fOptions->degree_mode;
+       fAngleModeRadianItem->SetMarked(!fOptions->degree_mode);
+       fAngleModeDegreeItem->SetMarked(fOptions->degree_mode);
+}
+
+
 void
 CalcView::SetKeypadMode(uint8 mode)
 {
@@ -1257,6 +1272,10 @@ CalcView::_CreatePopUpMenu(bool addKeypadModeMenuItems)
                new BMessage(MSG_OPTIONS_AUTO_NUM_LOCK));
        fAudioFeedbackItem = new BMenuItem(B_TRANSLATE("Audio Feedback"),
                new BMessage(MSG_OPTIONS_AUDIO_FEEDBACK));
+       fAngleModeRadianItem = new BMenuItem(B_TRANSLATE("Radian Mode"),
+               new BMessage(MSG_OPTIONS_ANGLE_MODE));
+       fAngleModeDegreeItem = new BMenuItem(B_TRANSLATE("Degree Mode"),
+               new BMessage(MSG_OPTIONS_ANGLE_MODE));
        if (addKeypadModeMenuItems) {
                fKeypadModeCompactItem = new BMenuItem(B_TRANSLATE("Compact"),
                        new BMessage(MSG_OPTIONS_KEYPAD_MODE_COMPACT), '0');
@@ -1269,6 +1288,8 @@ CalcView::_CreatePopUpMenu(bool addKeypadModeMenuItems)
        // apply current settings
        fAutoNumlockItem->SetMarked(fOptions->auto_num_lock);
        fAudioFeedbackItem->SetMarked(fOptions->audio_feedback);
+       fAngleModeRadianItem->SetMarked(!fOptions->degree_mode);
+       fAngleModeDegreeItem->SetMarked(fOptions->degree_mode);
 
        // construct menu
        fPopUpMenu = new BPopUpMenu("pop-up", false, false);
@@ -1277,6 +1298,9 @@ CalcView::_CreatePopUpMenu(bool addKeypadModeMenuItems)
        // TODO: Enable this when we use beep events which can be configured
        // in the Sounds preflet.
        //fPopUpMenu->AddItem(fAudioFeedbackItem);
+       fPopUpMenu->AddSeparatorItem();
+       fPopUpMenu->AddItem(fAngleModeRadianItem);
+       fPopUpMenu->AddItem(fAngleModeDegreeItem);
        if (addKeypadModeMenuItems) {
                fPopUpMenu->AddSeparatorItem();
                fPopUpMenu->AddItem(fKeypadModeCompactItem);
diff --git a/src/apps/deskcalc/CalcView.h b/src/apps/deskcalc/CalcView.h
index 16cf413..2c61fe7 100644
--- a/src/apps/deskcalc/CalcView.h
+++ b/src/apps/deskcalc/CalcView.h
@@ -16,6 +16,7 @@
 enum {
        MSG_OPTIONS_AUTO_NUM_LOCK                               = 'oanl',
        MSG_OPTIONS_AUDIO_FEEDBACK                              = 'oafb',
+       MSG_OPTIONS_ANGLE_MODE                                  = 'oamd',
        MSG_OPTIONS_KEYPAD_MODE_COMPACT                 = 'okmc',
        MSG_OPTIONS_KEYPAD_MODE_BASIC                   = 'okmb',
        MSG_OPTIONS_KEYPAD_MODE_SCIENTIFIC              = 'okms',
@@ -90,6 +91,9 @@ class CalcView : public BView {
                        // (option currently disabled)
                        void                            
ToggleAudioFeedback(void);
 
+                       // Toggle radian/degree mode
+                       void                            ToggleAngleMode(void);
+
                        // Set the keypad mode
                        void                            SetKeypadMode(uint8 
mode);
 
@@ -147,6 +151,10 @@ class CalcView : public BView {
                        BPopUpMenu*                     fPopUpMenu;
                        BMenuItem*                      fAutoNumlockItem;
                        BMenuItem*                      fAudioFeedbackItem;
+
+                       BMenuItem*                      fAngleModeRadianItem;
+                       BMenuItem*                      fAngleModeDegreeItem;
+
                        BMenuItem*                      fKeypadModeCompactItem;
                        BMenuItem*                      fKeypadModeBasicItem;
                        BMenuItem*                      
fKeypadModeScientificItem;
diff --git a/src/apps/deskcalc/CalcWindow.cpp b/src/apps/deskcalc/CalcWindow.cpp
index 0ccb142..f91d0d4 100644
--- a/src/apps/deskcalc/CalcWindow.cpp
+++ b/src/apps/deskcalc/CalcWindow.cpp
@@ -88,6 +88,10 @@ CalcWindow::MessageReceived(BMessage* message)
                        fCalcView->ToggleAudioFeedback();
                        break;
 
+               case MSG_OPTIONS_ANGLE_MODE:
+                       fCalcView->ToggleAngleMode();
+                       break;
+
                case MSG_OPTIONS_KEYPAD_MODE_COMPACT:
                        fCalcView->SetKeypadMode(KEYPAD_MODE_COMPACT);
                        break;
diff --git a/src/kits/shared/ExpressionParser.cpp 
b/src/kits/shared/ExpressionParser.cpp
index 6622433..4ea2387 100644
--- a/src/kits/shared/ExpressionParser.cpp
+++ b/src/kits/shared/ExpressionParser.cpp
@@ -338,7 +338,8 @@ class Tokenizer {
 
 
 ExpressionParser::ExpressionParser()
-       : fTokenizer(new Tokenizer())
+       :       fTokenizer(new Tokenizer()),
+               fDegreeMode(false)
 {
 }
 
@@ -349,6 +350,20 @@ ExpressionParser::~ExpressionParser()
 }
 
 
+bool
+ExpressionParser::DegreeMode()
+{
+       return fDegreeMode;
+}
+
+
+void
+ExpressionParser::SetDegreeMode(bool degrees)
+{
+       fDegreeMode = degrees;
+}
+
+
 void
 ExpressionParser::SetSupportHexInput(bool enabled)
 {
@@ -594,19 +609,36 @@ ExpressionParser::_ParseFunction(const Token& token)
                return _ParseFactorial(values[0].abs());
        } else if (strcasecmp("acos", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               if (fDegreeMode)
+                       values[0] = values[0] * MM_PI / 180;
+
                if (values[0] < -1 || values[0] > 1)
                        throw ParseException("out of domain", token.position);
+
                return _ParseFactorial(values[0].acos());
        } else if (strcasecmp("asin", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               if (fDegreeMode)
+                       values[0] = values[0] * MM_PI / 180;
+
                if (values[0] < -1 || values[0] > 1)
                        throw ParseException("out of domain", token.position);
+
                return _ParseFactorial(values[0].asin());
        } else if (strcasecmp("atan", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               if (fDegreeMode)
+                       values[0] = values[0] * MM_PI / 180;
+
                return _ParseFactorial(values[0].atan());
        } else if (strcasecmp("atan2", token.string.String()) == 0) {
                _InitArguments(values, 2);
+
+               if (fDegreeMode) {
+                       values[0] = values[0] * MM_PI / 180;
+                       values[1] = values[1] * MM_PI / 180;
+               }
+
                return _ParseFactorial(values[0].atan2(values[1]));
        } else if (strcasecmp("cbrt", token.string.String()) == 0) {
                _InitArguments(values, 1);
@@ -616,9 +648,13 @@ ExpressionParser::_ParseFunction(const Token& token)
                return _ParseFactorial(values[0].ceil());
        } else if (strcasecmp("cos", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               if (fDegreeMode)
+                       values[0] = values[0] * MM_PI / 180;
+
                return _ParseFactorial(values[0].cos());
        } else if (strcasecmp("cosh", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               // This function always uses radians
                return _ParseFactorial(values[0].cosh());
        } else if (strcasecmp("exp", token.string.String()) == 0) {
                _InitArguments(values, 1);
@@ -630,34 +666,46 @@ ExpressionParser::_ParseFunction(const Token& token)
                _InitArguments(values, 1);
                if (values[0] <= 0)
                        throw ParseException("out of domain", token.position);
+
                return _ParseFactorial(values[0].log());
        } else if (strcasecmp("log", token.string.String()) == 0) {
                _InitArguments(values, 1);
                if (values[0] <= 0)
                        throw ParseException("out of domain", token.position);
+
                return _ParseFactorial(values[0].log10());
        } else if (strcasecmp("pow", token.string.String()) == 0) {
                _InitArguments(values, 2);
                return _ParseFactorial(values[0].pow(values[1]));
        } else if (strcasecmp("sin", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               if (fDegreeMode)
+                       values[0] = values[0] * MM_PI / 180;
+
                return _ParseFactorial(values[0].sin());
        } else if (strcasecmp("sinh", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               // This function always uses radians
                return _ParseFactorial(values[0].sinh());
        } else if (strcasecmp("sqrt", token.string.String()) == 0) {
                _InitArguments(values, 1);
                if (values[0] < 0)
                        throw ParseException("out of domain", token.position);
+
                return _ParseFactorial(values[0].sqrt());
        } else if (strcasecmp("tan", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               if (fDegreeMode)
+                       values[0] = values[0] * MM_PI / 180;
+
                MAPM divided_by_half_pi = values[0] / MM_HALF_PI;
                if (divided_by_half_pi.is_integer() && 
divided_by_half_pi.is_odd())
                        throw ParseException("out of domain", token.position);
+
                return _ParseFactorial(values[0].tan());
        } else if (strcasecmp("tanh", token.string.String()) == 0) {
                _InitArguments(values, 1);
+               // This function always uses radians
                return _ParseFactorial(values[0].tanh());
        }
 


Other related posts:

  • » [haiku-commits] haiku: hrev44442 - src/apps/deskcalc src/kits/shared headers/private/shared - jscipione