[haiku-commits] haiku: hrev46684 - src/apps/deskcalc

  • From: jscipione@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 16 Jan 2014 01:01:34 +0100 (CET)

hrev46684 adds 1 changeset to branch 'master'
old head: 159d1fb69a57dfe50cafdbc9af1b9e99548e24f7
new head: 969fac14a7363e96cd67d2dda6ee3ef5a8c9bada
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=969fac1+%5E159d1fb

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

969fac1: Evaluate asynchronously in a separate thread
  
  Show calculating animation

                                     [ John Scipione <jscipione@xxxxxxxxx> ]

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

Revision:    hrev46684
Commit:      969fac14a7363e96cd67d2dda6ee3ef5a8c9bada
URL:         http://cgit.haiku-os.org/haiku/commit/?id=969fac1
Author:      John Scipione <jscipione@xxxxxxxxx>
Date:        Thu Jun 13 04:07:37 2013 UTC

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

2 files changed, 177 insertions(+), 20 deletions(-)
src/apps/deskcalc/CalcView.cpp | 188 +++++++++++++++++++++++++++++++++----
src/apps/deskcalc/CalcView.h   |   9 ++

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

diff --git a/src/apps/deskcalc/CalcView.cpp b/src/apps/deskcalc/CalcView.cpp
index b0ceda2..bfdd87b 100644
--- a/src/apps/deskcalc/CalcView.cpp
+++ b/src/apps/deskcalc/CalcView.cpp
@@ -50,6 +50,10 @@
 #define B_TRANSLATION_CONTEXT "CalcView"
 
 
+static const int32 kMsgCalculating = 'calc';
+static const int32 kMsgAnimateDots = 'dots';
+static const int32 kMsgDoneEvaluating = 'done';
+
 //const uint8 K_COLOR_OFFSET                           = 32;
 const float kFontScaleY                                                = 0.4f;
 const float kFontScaleX                                                = 0.4f;
@@ -57,6 +61,8 @@ const float kExpressionFontScaleY                     = 0.6f;
 const float kDisplayScaleY                                     = 0.2f;
 
 static const bigtime_t kFlashOnOffInterval     = 100000;
+static const bigtime_t kCalculatingInterval    = 1000000;
+static const bigtime_t kAnimationInterval      = 333333;
 
 static const float kMinimumWidthCompact                = 130.0f;
 static const float kMaximumWidthCompact                = 400.0f;
@@ -139,7 +145,11 @@ CalcView::CalcView(BRect frame, rgb_color rgbBaseColor, 
BMessage* settings)
        fPopUpMenu(NULL),
        fAutoNumlockItem(NULL),
        fAudioFeedbackItem(NULL),
-       fOptions(new CalcOptions())
+       fOptions(new CalcOptions()),
+       fEvaluateThread(-1),
+       fEvaluateMessageRunner(NULL),
+       fEvaluateSemaphore(B_BAD_SEM_ID),
+       fEnabled(true)
 {
        // tell the app server not to erase our b/g
        SetViewColor(B_TRANSPARENT_32_BIT);
@@ -172,7 +182,11 @@ CalcView::CalcView(BMessage* archive)
        fPopUpMenu(NULL),
        fAutoNumlockItem(NULL),
        fAudioFeedbackItem(NULL),
-       fOptions(new CalcOptions())
+       fOptions(new CalcOptions()),
+       fEvaluateThread(-1),
+       fEvaluateMessageRunner(NULL),
+       fEvaluateSemaphore(B_BAD_SEM_ID),
+       fEnabled(true)
 {
        // Do not restore the follow mode, in shelfs, we never follow.
        SetResizingMode(B_FOLLOW_NONE);
@@ -186,6 +200,8 @@ CalcView::~CalcView()
        delete fKeypad;
        delete fOptions;
        free(fKeypadDescription);
+       delete fEvaluateMessageRunner;
+       delete_sem(fEvaluateSemaphore);
 }
 
 
@@ -303,6 +319,80 @@ CalcView::MessageReceived(BMessage* message)
                                break;
                        }
 
+                       case kMsgAnimateDots:
+                       {
+                               int32 end = fExpressionTextView->TextLength();
+                               int32 start = end - 3;
+                               if (fEnabled || 
strcmp(fExpressionTextView->Text() + start, "...") != 0) {
+                                       // stop the message runner
+                                       delete fEvaluateMessageRunner;
+                                       fEvaluateMessageRunner = NULL;
+                                       break;
+                               }
+
+                               uint8 dot = 0;
+                               if (message->FindUInt8("dot", &dot) == B_OK) {
+                                       rgb_color fontColor = 
fExpressionTextView->HighColor();
+                                       rgb_color backColor = 
fExpressionTextView->LowColor();
+                                       fExpressionTextView->SetStylable(true);
+                                       
fExpressionTextView->SetFontAndColor(start, end, NULL, 0, &backColor);
+                                       
fExpressionTextView->SetFontAndColor(start + dot - 1, start + dot, NULL,
+                                               0, &fontColor);
+                                       fExpressionTextView->SetStylable(false);
+                               }
+
+                               dot++;
+                               if (dot == 4)
+                                       dot = 1;
+
+                               delete fEvaluateMessageRunner;
+                               BMessage animate(kMsgAnimateDots);
+                               animate.AddUInt8("dot", dot);
+                               fEvaluateMessageRunner = new (std::nothrow) 
BMessageRunner(
+                                       BMessenger(this), &animate, 
kAnimationInterval, 1);
+                               break;
+                       }
+
+                       case kMsgCalculating:
+                       {
+                               // calculation has taken more than 3 seconds
+                               if (fEnabled) {
+                                       // stop the message runner
+                                       delete fEvaluateMessageRunner;
+                                       fEvaluateMessageRunner = NULL;
+                                       break;
+                               }
+
+                               BString calculating;
+                               calculating << B_TRANSLATE("Calculating") << 
"...";
+                               
fExpressionTextView->SetText(calculating.String());
+
+                               delete fEvaluateMessageRunner;
+                               BMessage animate(kMsgAnimateDots);
+                               animate.AddUInt8("dot", 1U);
+                               fEvaluateMessageRunner = new (std::nothrow) 
BMessageRunner(
+                                       BMessenger(this), &animate, 
kAnimationInterval, 1);
+                               break;
+                       }
+
+                       case kMsgDoneEvaluating:
+                       {
+                               _SetEnabled(true);
+                               rgb_color fontColor = 
fExpressionTextView->HighColor();
+                               fExpressionTextView->SetFontAndColor(NULL, 0, 
&fontColor);
+
+                               const char* result;
+                               if (message->FindString("error", &result) == 
B_OK)
+                                       fExpressionTextView->SetText(result);
+                               else if (message->FindString("value", &result) 
== B_OK)
+                                       fExpressionTextView->SetValue(result);
+
+                               // stop the message runner
+                               delete fEvaluateMessageRunner;
+                               fEvaluateMessageRunner = NULL;
+                               break;
+                       }
+
                        default:
                                BView::MessageReceived(message);
                                break;
@@ -591,7 +681,8 @@ CalcView::FrameResized(float width, float height)
                ? fHeight : fHeight * kDisplayScaleY;
        BFont font(be_bold_font);
        font.SetSize(sizeDisp * kExpressionFontScaleY);
-       fExpressionTextView->SetFontAndColor(&font, B_FONT_ALL);
+       rgb_color fontColor = fExpressionTextView->HighColor();
+       fExpressionTextView->SetFontAndColor(&font, B_FONT_ALL, &fontColor);
 
        expressionRect.OffsetTo(B_ORIGIN);
        float inset = (expressionRect.Height() - 
fExpressionTextView->LineHeight(0)) / 2;
@@ -736,31 +827,39 @@ CalcView::SaveSettings(BMessage* archive) const
 void
 CalcView::Evaluate()
 {
-       BString expression = fExpressionTextView->Text();
-
-       if (expression.Length() == 0) {
+       if (fExpressionTextView->TextLength() == 0) {
                beep();
                return;
        }
 
-       _AudioFeedback(false);
-
-       // evaluate expression
-       BString value;
+       fEvaluateThread = spawn_thread(_EvaluateThread, "Evaluate Thread",
+               B_LOW_PRIORITY, this);
+       if (fEvaluateThread < B_OK) {
+               // failed to create evaluate thread, error out
+               fExpressionTextView->SetText(strerror(fEvaluateThread));
+               return;
+       }
 
-       try {
-               ExpressionParser parser;
-               parser.SetDegreeMode(fOptions->degree_mode);
-               value = parser.Evaluate(expression.String());
-       } catch (ParseException e) {
-               BString error(e.message.String());
-               error << " at " << (e.position + 1);
-               fExpressionTextView->SetText(error.String());
+       _AudioFeedback(false);
+       _SetEnabled(false);
+               // Disable input while we evaluate
+
+       status_t threadStatus = resume_thread(fEvaluateThread);
+       if (threadStatus != B_OK) {
+               // evaluate thread failed to start, error out
+               fExpressionTextView->SetText(strerror(threadStatus));
+               _SetEnabled(true);
                return;
        }
 
-       // render new result to display
-       fExpressionTextView->SetValue(value.String());
+       if (fEvaluateMessageRunner == NULL) {
+               BMessage message(kMsgCalculating);
+               fEvaluateMessageRunner = new (std::nothrow) BMessageRunner(
+                       BMessenger(this), &message, kCalculatingInterval, 1);
+               status_t runnerStatus = fEvaluateMessageRunner->InitCheck();
+               if (runnerStatus != B_OK)
+                       printf("Evaluate Message Runner: %s\n", 
strerror(runnerStatus));
+       }
 }
 
 
@@ -895,6 +994,41 @@ CalcView::SetKeypadMode(uint8 mode)
 // #pragma mark -
 
 
+/*static*/ status_t
+CalcView::_EvaluateThread(void* data)
+{
+       CalcView* calcView = reinterpret_cast<CalcView*>(data);
+       if (calcView == NULL)
+               return B_BAD_TYPE;
+
+       BMessenger messenger(calcView);
+       if (!messenger.IsValid())
+               return B_BAD_VALUE;
+
+       BString result;
+       status_t status = acquire_sem(calcView->fEvaluateSemaphore);
+       if (status == B_OK) {
+               ExpressionParser parser;
+               parser.SetDegreeMode(calcView->fOptions->degree_mode);
+               BString expression(calcView->fExpressionTextView->Text());
+               try {
+                       result = parser.Evaluate(expression.String());
+               } catch (ParseException e) {
+                       result << e.message.String() << " at " << (e.position + 
1);
+                       status = B_ERROR;
+               }
+               release_sem(calcView->fEvaluateSemaphore);
+       } else
+               result = strerror(status);
+
+       BMessage message(kMsgDoneEvaluating);
+       message.AddString(status == B_OK ? "value" : "error", result.String());
+       messenger.SendMessage(&message);
+
+       return status;
+}
+
+
 void
 CalcView::_Init(BMessage* settings)
 {
@@ -907,6 +1041,8 @@ CalcView::_Init(BMessage* settings)
 
        // fetch the calc icon for compact view
        _FetchAppIcon(fCalcIcon);
+
+       fEvaluateSemaphore = create_sem(1, "Evaluate Semaphore");
 }
 
 
@@ -1023,6 +1159,9 @@ CalcView::_ParseCalcDesc(const char* keypadDescription)
 void
 CalcView::_PressKey(int key)
 {
+       if (!fEnabled)
+               return;
+
        assert(key < (fRows * fColumns));
        assert(key >= 0);
 
@@ -1294,3 +1433,12 @@ CalcView::_IsEmbedded()
 {
        return Parent() != NULL && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 
0;
 }
+
+
+void
+CalcView::_SetEnabled(bool enable)
+{
+       fEnabled = enable;
+       fExpressionTextView->MakeSelectable(enable);
+       fExpressionTextView->MakeEditable(enable);
+}
diff --git a/src/apps/deskcalc/CalcView.h b/src/apps/deskcalc/CalcView.h
index a4a45bc..8d9b499 100644
--- a/src/apps/deskcalc/CalcView.h
+++ b/src/apps/deskcalc/CalcView.h
@@ -35,6 +35,7 @@ static const float kMaximumHeightBasic                = 
400.0f;
 class BString;
 class BMenuItem;
 class BMessage;
+class BMessageRunner;
 class BPopUpMenu;
 class CalcOptions;
 class CalcOptionsWindow;
@@ -97,6 +98,7 @@ class CalcView : public BView {
                        void                            SetKeypadMode(uint8 
mode);
 
  private:
+       static  status_t                        _EvaluateThread(void* data);
                        void                            _Init(BMessage* 
settings);
                        status_t                        _LoadSettings(BMessage* 
archive);
                        void                            _ParseCalcDesc(const 
char* keypadDescription);
@@ -119,6 +121,8 @@ class CalcView : public BView {
                        void                            _FetchAppIcon(BBitmap* 
into);
                        bool                            _IsEmbedded();
 
+                       void                            _SetEnabled(bool 
enable);
+
                        // grid dimensions
                        int16                           fColumns;
                        int16                           fRows;
@@ -161,6 +165,11 @@ class CalcView : public BView {
 
                        // calculator options.
                        CalcOptions*            fOptions;
+
+                       thread_id                       fEvaluateThread;
+                       BMessageRunner*         fEvaluateMessageRunner;
+                       sem_id                          fEvaluateSemaphore;
+                       bool                            fEnabled;
 };
 
 #endif // _CALC_VIEW_H


Other related posts: