Add a simple calculator with trigonometric functions
This commit is contained in:
parent
7d6169fb26
commit
e6ac1abda1
|
@ -0,0 +1,948 @@
|
|||
// calculator.cpp
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// A simple calculator with trigonometric functions
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <stack>
|
||||
|
||||
#include "fapp.h"
|
||||
#include "fdialog.h"
|
||||
#include "fmessagebox.h"
|
||||
|
||||
const long double PI = 3.141592653589793238L;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class Button
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
class Button : public FButton
|
||||
{
|
||||
private:
|
||||
bool checked;
|
||||
public:
|
||||
explicit Button (FWidget* parent=0); // constructor
|
||||
void setChecked(bool);
|
||||
void onKeyPress (FKeyEvent*);
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
Button::Button (FWidget* parent) : FButton(parent)
|
||||
{
|
||||
checked = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Button::setChecked(bool on)
|
||||
{
|
||||
if ( checked != on )
|
||||
{
|
||||
checked = on;
|
||||
|
||||
if ( checked )
|
||||
{
|
||||
setBackgroundColor(fc::Cyan);
|
||||
setFocusForegroundColor(fc::White);
|
||||
setFocusBackgroundColor(fc::Cyan);
|
||||
}
|
||||
else
|
||||
{
|
||||
setBackgroundColor(wc.button_active_bg);
|
||||
setFocusForegroundColor(wc.button_active_focus_fg);
|
||||
setFocusBackgroundColor(wc.button_active_focus_bg);
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Button::onKeyPress (FKeyEvent* event)
|
||||
{
|
||||
int key = event->key();
|
||||
|
||||
// catch the enter key
|
||||
if ( key == fc::Fkey_return || key == fc::Fkey_return )
|
||||
return;
|
||||
|
||||
FButton::onKeyPress(event);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class Calc
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
class Calc : public FDialog
|
||||
{
|
||||
private:
|
||||
bool error;
|
||||
bool arcus_mode;
|
||||
bool hyperbolic_mode;
|
||||
|
||||
enum button
|
||||
{
|
||||
Sine,
|
||||
Cosine,
|
||||
Tangent,
|
||||
Reciprocal,
|
||||
On,
|
||||
Natural_logarithm,
|
||||
Powers_of_e,
|
||||
Power,
|
||||
Square_root,
|
||||
Divide,
|
||||
Common_logarithm,
|
||||
Powers_of_ten,
|
||||
Parenthese_l,
|
||||
Parenthese_r,
|
||||
Multiply,
|
||||
Hyperbolic,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Subtract,
|
||||
Arcus,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Add,
|
||||
Pi,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Percent,
|
||||
Zero,
|
||||
Decimal_point,
|
||||
Change_sign,
|
||||
Equals,
|
||||
NUM_OF_BUTTONS
|
||||
};
|
||||
|
||||
long double a, b;
|
||||
uInt max_char;
|
||||
int last_key;
|
||||
char infix_operator;
|
||||
char last_infix_operator;
|
||||
FString input;
|
||||
int button_no[Calc::NUM_OF_BUTTONS];
|
||||
|
||||
struct stack_data
|
||||
{
|
||||
long double term;
|
||||
char infix_operator;
|
||||
};
|
||||
|
||||
std::stack<stack_data> bracket_stack;
|
||||
std::map<Calc::button, Button*> calculator_buttons;
|
||||
|
||||
private:
|
||||
void drawDispay();
|
||||
virtual void draw();
|
||||
bool isDataEntryKey(int);
|
||||
bool isOperatorKey(int);
|
||||
void setDisplay (long double);
|
||||
void setInfixOperator(char);
|
||||
void clearInfixOperator();
|
||||
void calcInfixOperator();
|
||||
|
||||
public:
|
||||
explicit Calc (FWidget* parent=0); // constructor
|
||||
~Calc(); // destructor
|
||||
void onKeyPress (FKeyEvent*);
|
||||
void onAccel (FAccelEvent*);
|
||||
void onClose (FCloseEvent*);
|
||||
void cb_buttonClicked (FWidget*, void*);
|
||||
|
||||
protected:
|
||||
void adjustSize();
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
Calc::Calc (FWidget* parent) : FDialog(parent)
|
||||
{
|
||||
error = false;
|
||||
arcus_mode = false;
|
||||
hyperbolic_mode = false;
|
||||
input = "";
|
||||
clearInfixOperator();
|
||||
last_infix_operator = '\0';
|
||||
max_char = 32;
|
||||
last_key = -1;
|
||||
a = b = 0.0L;
|
||||
|
||||
const wchar_t* button_text[Calc::NUM_OF_BUTTONS] =
|
||||
{
|
||||
L"&Sin",
|
||||
L"&Cos",
|
||||
L"&Tan",
|
||||
L"1/&x",
|
||||
L"&On",
|
||||
L"L&n",
|
||||
L"&e\x02e3",
|
||||
L"&y\x02e3",
|
||||
L"Sq&r",
|
||||
L"&\xf7",
|
||||
L"&Lg",
|
||||
L"10&\x02e3",
|
||||
L"&(",
|
||||
L"&)",
|
||||
L"&\xd7",
|
||||
L"&Hyp",
|
||||
L"&7",
|
||||
L"&8",
|
||||
L"&9",
|
||||
L"&-",
|
||||
L"&Arc",
|
||||
L"&4",
|
||||
L"&5",
|
||||
L"&6",
|
||||
L"&+",
|
||||
L"&\x03c0",
|
||||
L"&1",
|
||||
L"&2",
|
||||
L"&3",
|
||||
L"&%",
|
||||
L"&0",
|
||||
L"&.",
|
||||
L"&±",
|
||||
L"&="
|
||||
};
|
||||
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
setText ("calculator");
|
||||
setGeometry (19, 6, 37, 18);
|
||||
addAccelerator('q'); // press 'q' to quit
|
||||
setShadow();
|
||||
|
||||
for (int key=0; key < Calc::NUM_OF_BUTTONS; key++)
|
||||
{
|
||||
Button* btn = new Button(this);
|
||||
button_no[key] = key;
|
||||
|
||||
if ( key == Equals )
|
||||
btn->setGeometry(30, 15, 5, 3);
|
||||
else
|
||||
{
|
||||
int x, y, n;
|
||||
(key <= Three) ? n=0 : n=1;
|
||||
x = (key+n)%5*7 + 2;
|
||||
y = (key+n)/5*2 + 3;
|
||||
btn->setGeometry(x, y, 5, 1);
|
||||
}
|
||||
btn->setFlat();
|
||||
btn->setNoUnderline();
|
||||
btn->unsetClickAnimation();
|
||||
btn->setText(button_text[key]);
|
||||
btn->setDoubleFlatLine(fc::top);
|
||||
if ( key <= Three )
|
||||
btn->setDoubleFlatLine(fc::bottom);
|
||||
|
||||
btn->addCallback
|
||||
(
|
||||
"clicked",
|
||||
this,
|
||||
reinterpret_cast<FWidget::FMemberCallback>(&Calc::cb_buttonClicked),
|
||||
&button_no[key]
|
||||
);
|
||||
|
||||
calculator_buttons[button(key)] = btn;
|
||||
|
||||
}
|
||||
|
||||
calculator_buttons[On]->addAccelerator(fc::Fkey_dc); // del key
|
||||
calculator_buttons[On]->setFocus();
|
||||
calculator_buttons[Pi]->addAccelerator('p');
|
||||
calculator_buttons[Power]->addAccelerator('^');
|
||||
calculator_buttons[Divide]->addAccelerator('/');
|
||||
calculator_buttons[Powers_of_ten]->addAccelerator('d');
|
||||
calculator_buttons[Multiply]->addAccelerator('*');
|
||||
calculator_buttons[Decimal_point]->addAccelerator(',');
|
||||
calculator_buttons[Change_sign]->addAccelerator('#');
|
||||
calculator_buttons[Equals]->addAccelerator(fc::Fkey_return);
|
||||
calculator_buttons[Equals]->addAccelerator(fc::Fkey_enter);
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
Calc::~Calc()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::drawDispay()
|
||||
{
|
||||
FString display = input;
|
||||
setUpdateVTerm(false);
|
||||
|
||||
if ( display.isNull() || display.isEmpty() )
|
||||
display = L'0';
|
||||
|
||||
if ( display.right(3) == L"-0." )
|
||||
display = L'0';
|
||||
|
||||
if ( display.back() == L'.' && display.getLength() > 1 )
|
||||
display = display.left(display.getLength() - 1);
|
||||
|
||||
if ( ! display.isEmpty() && display.getLength() < max_char )
|
||||
display.insert(FString(max_char - display.getLength(), L' '), 0);
|
||||
|
||||
if ( display.getLength() > max_char )
|
||||
display = display.left(max_char);
|
||||
|
||||
if ( infix_operator )
|
||||
display[1] = infix_operator;
|
||||
|
||||
if ( error )
|
||||
display = " Error ";
|
||||
|
||||
setColor(fc::Black, fc::LightGray);
|
||||
gotoxy (xpos+xmin+1, ypos+ymin+1);
|
||||
print(display);
|
||||
print(L' ');
|
||||
|
||||
setColor(fc::Black, fc::White);
|
||||
if ( isNewFont() )
|
||||
{
|
||||
FString bottom_line(33, wchar_t(fc::NF_border_line_bottom));
|
||||
gotoxy (xpos+xmin+1, ypos+ymin);
|
||||
print(bottom_line);
|
||||
gotoxy (xpos+xmin+0, ypos+ymin+1);
|
||||
print (wchar_t(fc::NF_rev_border_line_right));
|
||||
gotoxy (xpos+xmin+34, ypos+ymin+1);
|
||||
print (wchar_t(fc::NF_border_line_left));
|
||||
FString top_bottom_line_5(5, wchar_t(fc::NF_border_line_up_and_down));
|
||||
FString top_line_2(2, wchar_t(fc::NF_border_line_upper));
|
||||
gotoxy (xpos+xmin+1, ypos+ymin+2);
|
||||
print ( top_bottom_line_5 + top_line_2
|
||||
+ top_bottom_line_5 + top_line_2
|
||||
+ top_bottom_line_5 + top_line_2
|
||||
+ top_bottom_line_5 + top_line_2
|
||||
+ top_bottom_line_5);
|
||||
}
|
||||
else
|
||||
{
|
||||
FString separator = FString(wchar_t(fc::BoxDrawingsVerticalAndRight))
|
||||
+ FString(35, wchar_t(fc::BoxDrawingsHorizontal))
|
||||
+ FString(wchar_t(fc::BoxDrawingsVerticalAndLeft));
|
||||
gotoxy (xpos+xmin-1, ypos+ymin+2);
|
||||
print(separator);
|
||||
}
|
||||
setUpdateVTerm(true);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::draw()
|
||||
{
|
||||
FDialog::draw();
|
||||
drawDispay();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool Calc::isDataEntryKey (int key)
|
||||
{
|
||||
// test if key is in {'.', '0'..'9'}
|
||||
int data_entry_keys[] =
|
||||
{
|
||||
Decimal_point,
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine
|
||||
};
|
||||
|
||||
int* iter = std::find (data_entry_keys, data_entry_keys+11, key);
|
||||
|
||||
if ( iter != data_entry_keys+11 )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool Calc::isOperatorKey(int key)
|
||||
{
|
||||
// test if key is in {'*', '/', '+', '-', '^', '='}
|
||||
int operators[] =
|
||||
{
|
||||
Multiply,
|
||||
Divide,
|
||||
Add,
|
||||
Subtract,
|
||||
Power,
|
||||
Equals
|
||||
};
|
||||
|
||||
int* iter = std::find (operators, operators+6, key);
|
||||
|
||||
if ( iter != operators+6 )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::setDisplay (long double d)
|
||||
{
|
||||
char buffer[32];
|
||||
snprintf (buffer, sizeof(buffer), "%31.11Lg", d);
|
||||
input = buffer;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline void Calc::setInfixOperator(char c)
|
||||
{
|
||||
infix_operator = c;
|
||||
last_infix_operator = infix_operator;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline void Calc::clearInfixOperator()
|
||||
{
|
||||
infix_operator = '\0';
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::calcInfixOperator()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
switch ( infix_operator )
|
||||
{
|
||||
case '*':
|
||||
if ( a != 0.0L )
|
||||
{
|
||||
// ln(a * b) = ln(a) + ln(b)
|
||||
if ( log(abs(a)) + log(abs(b)) <= log(LDBL_MAX) )
|
||||
a *= b;
|
||||
else
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
b = 0.0L;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
if ( b != 0.0L )
|
||||
a /= b;
|
||||
else
|
||||
error = true;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
if ( a != 0.0L )
|
||||
{
|
||||
if ( log(abs(a)) + log(abs(1 + b/a)) <= log(LDBL_MAX) )
|
||||
a += b;
|
||||
else
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
a = b;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if ( a != 0.0L )
|
||||
{
|
||||
if ( log(abs(a)) + log(abs(1 - b/a)) <= log(LDBL_MAX) )
|
||||
a -= b;
|
||||
else
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
a = b * (-1.0L);
|
||||
break;
|
||||
|
||||
case '^':
|
||||
a = pow(a, b);
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
clearInfixOperator();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::onKeyPress (FKeyEvent* event)
|
||||
{
|
||||
int len = int(input.getLength());
|
||||
int key = event->key();
|
||||
|
||||
switch ( key )
|
||||
{
|
||||
case fc::Fkey_backspace:
|
||||
if ( len > 0 )
|
||||
{
|
||||
if ( len == 1 )
|
||||
input = "";
|
||||
else
|
||||
input = input.left(input.getLength() - 1);
|
||||
a = atof(input.c_str());
|
||||
drawDispay();
|
||||
updateTerminal();
|
||||
}
|
||||
event->accept();
|
||||
break;
|
||||
|
||||
case fc::Fkey_escape:
|
||||
case fc::Fkey_escape_mintty:
|
||||
FAccelEvent a_ev(Accelerator_Event, getFocusWidget());
|
||||
calculator_buttons[On]->onAccel(&a_ev);
|
||||
event->accept();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::onAccel (FAccelEvent* ev)
|
||||
{
|
||||
close();
|
||||
ev->accept();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::onClose (FCloseEvent* event)
|
||||
{
|
||||
int ret = FMessageBox::info ( this, "Quit",
|
||||
"Do you really want\n"
|
||||
"to quit the program ?",
|
||||
FMessageBox::Yes,
|
||||
FMessageBox::No );
|
||||
|
||||
(ret == FMessageBox::Yes) ? event->accept() : event->ignore();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::cb_buttonClicked (FWidget*, void* data_ptr)
|
||||
{
|
||||
int key;
|
||||
long double* x;
|
||||
|
||||
using namespace std;
|
||||
|
||||
if ( infix_operator )
|
||||
x = &b;
|
||||
else
|
||||
x = &a;
|
||||
|
||||
key = *(static_cast<int*>(data_ptr));
|
||||
|
||||
switch ( key )
|
||||
{
|
||||
case Sine: // sin
|
||||
if ( hyperbolic_mode )
|
||||
{
|
||||
if ( arcus_mode )
|
||||
{
|
||||
*x = log(*x + sqrt((*x) * (*x) + 1));
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
if ( *x == INFINITY )
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
*x = sinh(*x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( arcus_mode )
|
||||
*x = asin(*x) * 180.0L/PI;
|
||||
else
|
||||
*x = sin(*x * PI/180.0L);
|
||||
}
|
||||
if ( errno == EDOM )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
arcus_mode = false;
|
||||
hyperbolic_mode = false;
|
||||
calculator_buttons[Arcus]->setChecked(false);
|
||||
calculator_buttons[Hyperbolic]->setChecked(false);
|
||||
break;
|
||||
|
||||
case Cosine: // cos
|
||||
if ( hyperbolic_mode )
|
||||
{
|
||||
if ( arcus_mode )
|
||||
{
|
||||
*x = log(*x + sqrt((*x) * (*x) - 1));
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
if ( *x == INFINITY )
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
*x = cosh(*x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( arcus_mode )
|
||||
*x = acos(*x) * 180.0L/PI;
|
||||
else
|
||||
*x = cos(*x * PI/180.0L);
|
||||
}
|
||||
if ( errno == EDOM )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
arcus_mode = false;
|
||||
hyperbolic_mode = false;
|
||||
calculator_buttons[Arcus]->setChecked(false);
|
||||
calculator_buttons[Hyperbolic]->setChecked(false);
|
||||
break;
|
||||
|
||||
case Tangent: // tan
|
||||
if ( hyperbolic_mode )
|
||||
{
|
||||
if ( arcus_mode )
|
||||
if ( *x < 1 )
|
||||
{
|
||||
*x = 0.5L * log((1+(*x))/(1-(*x)));
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
error = true;
|
||||
else
|
||||
*x = tanh(*x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( arcus_mode )
|
||||
*x = atan(*x) * 180.0L/PI;
|
||||
else
|
||||
if ( fmod(*x,180.0L) != 0.0L && fmod(*x,90.0L) == 0.0L )
|
||||
error = true;
|
||||
else if ( fmod(*x,180.0L) == 0.0L )
|
||||
*x = 0.0L;
|
||||
else
|
||||
*x = tan(*x * PI/180.0L);
|
||||
}
|
||||
if ( errno == EDOM )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
arcus_mode = false;
|
||||
hyperbolic_mode = false;
|
||||
calculator_buttons[Arcus]->setChecked(false);
|
||||
calculator_buttons[Hyperbolic]->setChecked(false);
|
||||
break;
|
||||
|
||||
case Reciprocal: // 1/x
|
||||
if ( *x == 0.0L )
|
||||
error = true;
|
||||
else
|
||||
{
|
||||
*x = 1/(*x);
|
||||
setDisplay(*x);
|
||||
}
|
||||
break;
|
||||
|
||||
case On:
|
||||
error = false;
|
||||
arcus_mode = false;
|
||||
hyperbolic_mode = false;
|
||||
calculator_buttons[Arcus]->setChecked(false);
|
||||
calculator_buttons[Hyperbolic]->setChecked(false);
|
||||
input = "";
|
||||
clearInfixOperator();
|
||||
last_infix_operator = '\0';
|
||||
a = b = 0.0L;
|
||||
break;
|
||||
|
||||
case Natural_logarithm: // ln
|
||||
*x = log(*x);
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Powers_of_e: // eˣ
|
||||
*x = exp(*x);
|
||||
if ( errno == ERANGE )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Power: // yˣ
|
||||
if ( ! isOperatorKey(last_key) )
|
||||
calcInfixOperator();
|
||||
setDisplay(*x);
|
||||
setInfixOperator('^');
|
||||
break;
|
||||
|
||||
case Square_root: // sqrt
|
||||
*x = sqrt(*x);
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Divide: // ÷
|
||||
if ( ! isOperatorKey(last_key) )
|
||||
calcInfixOperator();
|
||||
setDisplay(a);
|
||||
setInfixOperator('/');
|
||||
break;
|
||||
|
||||
case Common_logarithm: // lg
|
||||
*x = log10(*x);
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Powers_of_ten: // 10ˣ
|
||||
*x = pow(10,*x);
|
||||
if ( errno == EDOM || errno == ERANGE )
|
||||
error = true;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Parenthese_l: // (
|
||||
{
|
||||
stack_data d = { a, infix_operator };
|
||||
bracket_stack.push(d);
|
||||
clearInfixOperator();
|
||||
input = "";
|
||||
a = b = 0.0L;
|
||||
setDisplay(a);
|
||||
}
|
||||
break;
|
||||
|
||||
case Parenthese_r: // )
|
||||
if ( ! bracket_stack.empty() )
|
||||
{
|
||||
calcInfixOperator();
|
||||
setDisplay(a);
|
||||
stack_data d = bracket_stack.top();
|
||||
bracket_stack.pop();
|
||||
b = d.term;
|
||||
infix_operator = d.infix_operator;
|
||||
last_infix_operator = infix_operator;
|
||||
}
|
||||
break;
|
||||
|
||||
case Multiply: // *
|
||||
if ( ! isOperatorKey(last_key) )
|
||||
calcInfixOperator();
|
||||
setDisplay(a);
|
||||
setInfixOperator('*');
|
||||
break;
|
||||
|
||||
case Hyperbolic: // hyp
|
||||
hyperbolic_mode = ! hyperbolic_mode;
|
||||
calculator_buttons[Hyperbolic]->setChecked(hyperbolic_mode);
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Seven: // 7
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '7';
|
||||
else
|
||||
input = '7';
|
||||
}
|
||||
break;
|
||||
|
||||
case Eight: // 8
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '8';
|
||||
else
|
||||
input = '8';
|
||||
}
|
||||
break;
|
||||
|
||||
case Nine: // 9
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '9';
|
||||
else
|
||||
input = '9';
|
||||
}
|
||||
break;
|
||||
|
||||
case Subtract: // -
|
||||
if ( ! isOperatorKey(last_key) )
|
||||
calcInfixOperator();
|
||||
setDisplay(a);
|
||||
setInfixOperator('-');
|
||||
break;
|
||||
|
||||
case Arcus: // arc
|
||||
arcus_mode = ! arcus_mode;
|
||||
calculator_buttons[Arcus]->setChecked(arcus_mode);
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Four: // 4
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '4';
|
||||
else
|
||||
input = '4';
|
||||
}
|
||||
break;
|
||||
|
||||
case Five: // 5
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '5';
|
||||
else
|
||||
input = '5';
|
||||
}
|
||||
break;
|
||||
|
||||
case Six: // 6
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '6';
|
||||
else
|
||||
input = '6';
|
||||
}
|
||||
break;
|
||||
|
||||
case Add: // +
|
||||
if ( ! isOperatorKey(last_key) )
|
||||
calcInfixOperator();
|
||||
setDisplay(a);
|
||||
setInfixOperator('+');
|
||||
break;
|
||||
|
||||
case Pi: // π
|
||||
*x = PI;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case One: // 1
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '1';
|
||||
else
|
||||
input = '1';
|
||||
}
|
||||
break;
|
||||
|
||||
case Two: // 2
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '2';
|
||||
else
|
||||
input = '2';
|
||||
}
|
||||
break;
|
||||
|
||||
case Three: // 3
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '3';
|
||||
else
|
||||
input = '3';
|
||||
}
|
||||
break;
|
||||
|
||||
case Percent: // %
|
||||
infix_operator = last_infix_operator;
|
||||
*x /= 100.0L;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Zero: // 0
|
||||
if ( input.getLength() < max_char )
|
||||
{
|
||||
if ( isDataEntryKey(last_key) )
|
||||
input += '0';
|
||||
else
|
||||
input = '0';
|
||||
}
|
||||
break;
|
||||
|
||||
case Decimal_point: // .
|
||||
if ( ! input.includes('.') )
|
||||
input += '.';
|
||||
break;
|
||||
|
||||
case Change_sign: // ±
|
||||
*x *= -1.0L;
|
||||
setDisplay(*x);
|
||||
break;
|
||||
|
||||
case Equals: // =
|
||||
infix_operator = last_infix_operator;
|
||||
calcInfixOperator();
|
||||
setDisplay(a);
|
||||
break;
|
||||
} // end of switch
|
||||
|
||||
if ( ! input.isEmpty() )
|
||||
{
|
||||
if ( isDataEntryKey(key) )
|
||||
*x = atof(input.c_str());
|
||||
else
|
||||
{
|
||||
// remove trailing zeros
|
||||
while ( ! input.includes(L'e')
|
||||
&& input.includes(L'.')
|
||||
&& input.back() == L'0' )
|
||||
input = input.left(input.getLength()-1);
|
||||
}
|
||||
}
|
||||
|
||||
drawDispay();
|
||||
updateTerminal();
|
||||
|
||||
if ( infix_operator && ! isDataEntryKey(key) )
|
||||
input = "";
|
||||
last_key = key;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void Calc::adjustSize()
|
||||
{
|
||||
int pw = parentWidget()->getWidth();
|
||||
int ph = parentWidget()->getHeight();
|
||||
setX (1 + (pw - getWidth()) / 2, false);
|
||||
setY (1 + (ph - getHeight()) / 2, false);
|
||||
FDialog::adjustSize();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// main part
|
||||
//----------------------------------------------------------------------
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
// Create the application object
|
||||
FApplication app(argc, argv);
|
||||
|
||||
// Create a calculator object
|
||||
Calc calculator(&app);
|
||||
|
||||
app.setMainWidget(&calculator);
|
||||
calculator.show();
|
||||
return app.exec();
|
||||
}
|
Loading…
Reference in New Issue