Quite a bunch of changes... but it doesn't work perfectly yet.
I ran into an obscure Pe bug which resulted in me overwriting the wrong file... but then the machine KDLd, which it almost never does... and I got lucky and the file was there again... But this teaches me to commit more often. * replaced expression area with a custom text view * added expression string history (a bit dumb yet) * added option to hide the keypad git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17767 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c13a4ddf0f
commit
b4d21c8325
@ -20,11 +20,46 @@
|
||||
|
||||
CalcOptions::CalcOptions()
|
||||
: auto_num_lock(true),
|
||||
audio_feedback(false)
|
||||
audio_feedback(false),
|
||||
show_keypad(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcOptions::LoadSettings(const BMessage* archive)
|
||||
{
|
||||
bool option;
|
||||
|
||||
if (archive->FindBool("auto num lock", &option) == B_OK)
|
||||
auto_num_lock = option;
|
||||
|
||||
if (archive->FindBool("audio feedback", &option) == B_OK)
|
||||
audio_feedback = option;
|
||||
|
||||
if (archive->FindBool("show keypad", &option) == B_OK)
|
||||
show_keypad = option;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CalcOptions::SaveSettings(BMessage* archive) const
|
||||
{
|
||||
status_t ret = archive->AddBool("auto num lock", auto_num_lock);
|
||||
|
||||
if (ret == B_OK)
|
||||
ret = archive->AddBool("audio feedback", audio_feedback);
|
||||
|
||||
if (ret == B_OK)
|
||||
ret = archive->AddBool("show keypad", show_keypad);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
CalcOptionsWindow::CalcOptionsWindow(BRect frame, CalcOptions *options,
|
||||
BMessage* quitMessage,
|
||||
BHandler* target)
|
||||
@ -44,6 +79,8 @@ CalcOptionsWindow::CalcOptionsWindow(BRect frame, CalcOptions *options,
|
||||
|
||||
// create interface components
|
||||
float y = 16.0f, vw, vh;
|
||||
|
||||
// auto numlock
|
||||
BRect viewframe(4.0f, y, frame.right, y + 16.0f);
|
||||
fAutoNumLockCheckBox = new BCheckBox(viewframe,
|
||||
"autoNumLockCheckBox", "Auto Num Lock", NULL);
|
||||
@ -53,7 +90,8 @@ CalcOptionsWindow::CalcOptionsWindow(BRect frame, CalcOptions *options,
|
||||
bg->AddChild(fAutoNumLockCheckBox);
|
||||
fAutoNumLockCheckBox->ResizeToPreferred();
|
||||
y += fAutoNumLockCheckBox->Frame().Height();
|
||||
|
||||
|
||||
// audio feedback
|
||||
viewframe.Set(4.0f, y, frame.right, y + 16.0f);
|
||||
fAudioFeedbackCheckBox = new BCheckBox(viewframe,
|
||||
"audioFeedbackCheckBox", "Audio Feedback", NULL);
|
||||
@ -63,17 +101,29 @@ CalcOptionsWindow::CalcOptionsWindow(BRect frame, CalcOptions *options,
|
||||
bg->AddChild(fAudioFeedbackCheckBox);
|
||||
fAudioFeedbackCheckBox->ResizeToPreferred();
|
||||
y += fAudioFeedbackCheckBox->Frame().Height();
|
||||
|
||||
// show keypad
|
||||
viewframe.Set(4.0f, y, frame.right, y + 16.0f);
|
||||
fShowKeypadCheckBox = new BCheckBox(viewframe,
|
||||
"showKeypadCheckBox", "Show Keypad", NULL);
|
||||
if (fOptions->show_keypad) {
|
||||
fShowKeypadCheckBox->SetValue(B_CONTROL_ON);
|
||||
}
|
||||
bg->AddChild(fShowKeypadCheckBox);
|
||||
fShowKeypadCheckBox->ResizeToPreferred();
|
||||
y += fShowKeypadCheckBox->Frame().Height();
|
||||
|
||||
// create buttons
|
||||
viewframe.Set(0.0f, 0.0f, 40.0f, 40.0f);
|
||||
fOkButton = new BButton(viewframe, "okButton", "OK",
|
||||
new BMessage(B_QUIT_REQUESTED));
|
||||
fOkButton->MakeDefault(true);
|
||||
fOkButton->GetPreferredSize(&vw, &vh);
|
||||
fOkButton->ResizeTo(vw, vh);
|
||||
fOkButton->MoveTo(frame.right - vw - 8.0f,
|
||||
frame.bottom - vh - 8.0f);
|
||||
bg->AddChild(fOkButton);
|
||||
|
||||
fOkButton->MakeDefault(true);
|
||||
|
||||
float cw, ch;
|
||||
fCancelButton = new BButton(viewframe, "cancelButton", "Cancel",
|
||||
@ -101,6 +151,9 @@ CalcOptionsWindow::QuitRequested()
|
||||
// audio feedback
|
||||
fOptions->audio_feedback = fAudioFeedbackCheckBox->Value() == B_CONTROL_ON;
|
||||
|
||||
// show keypad
|
||||
fOptions->show_keypad = fShowKeypadCheckBox->Value() == B_CONTROL_ON;
|
||||
|
||||
// notify target of our demise
|
||||
if (fQuitMessage && fTarget && fTarget->Looper()) {
|
||||
fQuitMessage->AddRect("window frame", Frame());
|
||||
|
@ -16,8 +16,12 @@
|
||||
struct CalcOptions {
|
||||
bool auto_num_lock; // automatically activate numlock
|
||||
bool audio_feedback; // provide audio feedback
|
||||
bool show_keypad; // show or hide the buttons
|
||||
|
||||
CalcOptions();
|
||||
CalcOptions();
|
||||
|
||||
void LoadSettings(const BMessage* archive);
|
||||
status_t SaveSettings(BMessage* archive) const;
|
||||
};
|
||||
|
||||
class BCheckBox;
|
||||
@ -41,6 +45,8 @@ class CalcOptionsWindow : public BWindow {
|
||||
|
||||
BCheckBox* fAutoNumLockCheckBox;
|
||||
BCheckBox* fAudioFeedbackCheckBox;
|
||||
BCheckBox* fShowKeypadCheckBox;
|
||||
|
||||
BButton* fOkButton;
|
||||
BButton* fCancelButton;
|
||||
};
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "CalcApplication.h"
|
||||
#include "CalcOptionsWindow.h"
|
||||
#include "ExpressionTextView.h"
|
||||
#include "Parser.h"
|
||||
|
||||
|
||||
@ -66,7 +67,7 @@ CalcView *CalcView::Instantiate(BMessage *archive)
|
||||
|
||||
|
||||
CalcView::CalcView(BRect frame, rgb_color rgbBaseColor)
|
||||
: BView(frame, "calc-view", B_FOLLOW_ALL_SIDES,
|
||||
: BView(frame, "DeskCalc", B_FOLLOW_ALL_SIDES,
|
||||
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
|
||||
fColums(5),
|
||||
fRows(4),
|
||||
@ -74,22 +75,25 @@ CalcView::CalcView(BRect frame, rgb_color rgbBaseColor)
|
||||
fBaseColor(rgbBaseColor),
|
||||
fExpressionBGColor((rgb_color){ 0, 0, 0, 255 }),
|
||||
|
||||
fWidth(frame.Width()),
|
||||
fHeight(frame.Height()),
|
||||
fWidth(1),
|
||||
fHeight(1),
|
||||
|
||||
fKeypadDescription(strdup(kDefaultKeypadDescription)),
|
||||
fKeypad(NULL),
|
||||
|
||||
fExpression(""),
|
||||
|
||||
fAboutItem(NULL),
|
||||
fOptionsItem(NULL),
|
||||
fPopUpMenu(NULL),
|
||||
|
||||
fOptions(new CalcOptions()),
|
||||
fOptionsWindow(NULL),
|
||||
fOptionsWindowFrame(30.0, 50.0, 230.0, 200.0)
|
||||
fOptionsWindowFrame(30.0, 50.0, 230.0, 200.0),
|
||||
fShowKeypad(true)
|
||||
{
|
||||
// create expression text view
|
||||
fExpressionTextView = new ExpressionTextView(_ExpressionRect(), this);
|
||||
AddChild(fExpressionTextView);
|
||||
|
||||
// tell the app server not to erase our b/g
|
||||
SetViewColor(B_TRANSPARENT_32_BIT);
|
||||
|
||||
@ -112,27 +116,28 @@ CalcView::CalcView(BMessage* archive)
|
||||
fBaseColor((rgb_color){ 128, 128, 128, 255 }),
|
||||
fExpressionBGColor((rgb_color){ 0, 0, 0, 255 }),
|
||||
|
||||
fWidth(1),
|
||||
fHeight(1),
|
||||
|
||||
fKeypadDescription(strdup(kDefaultKeypadDescription)),
|
||||
fKeypad(NULL),
|
||||
|
||||
fExpression(""),
|
||||
|
||||
fAboutItem(NULL),
|
||||
fOptionsItem(NULL),
|
||||
fPopUpMenu(NULL),
|
||||
|
||||
fOptions(new CalcOptions()),
|
||||
fOptionsWindow(NULL),
|
||||
fOptionsWindowFrame(30.0, 50.0, 230.0, 200.0)
|
||||
fOptionsWindowFrame(30.0, 50.0, 230.0, 200.0),
|
||||
fShowKeypad(true)
|
||||
{
|
||||
// create expression text view
|
||||
fExpressionTextView = new ExpressionTextView(_ExpressionRect(), this);
|
||||
AddChild(fExpressionTextView);
|
||||
|
||||
// read data from archive
|
||||
LoadSettings(archive);
|
||||
|
||||
// load frame dimensions
|
||||
BRect frame = Frame();
|
||||
fWidth = frame.Width();
|
||||
fHeight = frame.Height();
|
||||
|
||||
// create pop-up menu system
|
||||
_CreatePopUpMenu();
|
||||
}
|
||||
@ -146,6 +151,16 @@ CalcView::~CalcView()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::AttachedToWindow()
|
||||
{
|
||||
SetFont(be_bold_font);
|
||||
|
||||
BRect frame(Frame());
|
||||
FrameResized(frame.Width(), frame.Height());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::MessageReceived(BMessage* message)
|
||||
{
|
||||
@ -211,6 +226,8 @@ CalcView::MessageReceived(BMessage* message)
|
||||
BRect frame;
|
||||
if (message->FindRect("window frame", &frame) == B_OK)
|
||||
fOptionsWindowFrame = frame;
|
||||
|
||||
_ShowKeypad(fOptions->show_keypad);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -225,38 +242,15 @@ CalcView::MessageReceived(BMessage* message)
|
||||
void
|
||||
CalcView::Draw(BRect updateRect)
|
||||
{
|
||||
rgb_color rgbWhite = { 255, 255, 255, 0 };
|
||||
if (!fShowKeypad)
|
||||
return;
|
||||
|
||||
// calculate grid sizes
|
||||
float sizeDisp = fHeight * K_DISPLAY_YPROP;
|
||||
BRect keypadRect(_KeypadRect());
|
||||
float sizeDisp = keypadRect.top;
|
||||
float sizeCol = fWidth / (float)fColums;
|
||||
float sizeRow = (fHeight - sizeDisp) / (float)fRows;
|
||||
|
||||
// setup areas
|
||||
BRect displayRect(0.0, 0.0, fWidth, sizeDisp);
|
||||
BRect keypadRect(0.0, sizeDisp, fWidth, fHeight);
|
||||
|
||||
SetFont(be_bold_font);
|
||||
|
||||
// ****** DISPLAY Area
|
||||
if (updateRect.Intersects(displayRect)) {
|
||||
|
||||
// paint display b/g
|
||||
SetHighColor(fExpressionBGColor);
|
||||
FillRect(updateRect & displayRect);
|
||||
|
||||
// render display text
|
||||
SetHighColor(rgbWhite);
|
||||
SetLowColor(fExpressionBGColor);
|
||||
SetDrawingMode(B_OP_COPY);
|
||||
SetFontSize(sizeDisp * K_FONT_YPROP);
|
||||
float baselineOffset = sizeDisp * (1.0 - K_FONT_YPROP) * 0.5;
|
||||
DrawString(fExpression.String(),
|
||||
BPoint(fWidth - StringWidth(fExpression.String()),
|
||||
sizeDisp - baselineOffset));
|
||||
}
|
||||
|
||||
// ****** KEYPAD Area
|
||||
if (updateRect.Intersects(keypadRect)) {
|
||||
// TODO: support pressed keys
|
||||
|
||||
@ -301,10 +295,10 @@ CalcView::Draw(BRect updateRect)
|
||||
|
||||
// render key symbols
|
||||
float halfSizeCol = sizeCol * 0.5f;
|
||||
SetHighColor(rgbWhite);
|
||||
SetHighColor(fButtonTextColor);
|
||||
SetLowColor(fBaseColor);
|
||||
SetDrawingMode(B_OP_COPY);
|
||||
SetFontSize(((fHeight - sizeDisp)/(float)fRows) * K_FONT_YPROP);
|
||||
SetFontSize(((fHeight - sizeDisp) / (float)fRows) * K_FONT_YPROP);
|
||||
float baselineOffset = ((fHeight - sizeDisp) / (float)fRows)
|
||||
* (1.0 - K_FONT_YPROP) * 0.5;
|
||||
CalcKey *key = fKeypad;
|
||||
@ -347,25 +341,25 @@ CalcView::MouseDown(BPoint point)
|
||||
// click on display, initiate drag if appropriate
|
||||
if ((point.y - sizeDisp) < 0.0) {
|
||||
// only drag if there's some text
|
||||
if (fExpression.Length() > 0) {
|
||||
// assemble drag message
|
||||
BMessage dragmsg(B_MIME_DATA);
|
||||
dragmsg.AddData("text/plain",
|
||||
B_MIME_TYPE,
|
||||
fExpression.String(),
|
||||
fExpression.Length());
|
||||
|
||||
// initiate drag & drop
|
||||
SetFontSize(sizeDisp * K_FONT_YPROP);
|
||||
float left = fWidth;
|
||||
float textWidth = StringWidth(fExpression.String());
|
||||
if (textWidth < fWidth)
|
||||
left -= textWidth;
|
||||
else
|
||||
left = 0;
|
||||
BRect displayRect(left, 0.0, fWidth, sizeDisp);
|
||||
DragMessage(&dragmsg, displayRect);
|
||||
}
|
||||
// if (fExpression.Length() > 0) {
|
||||
// // assemble drag message
|
||||
// BMessage dragmsg(B_MIME_DATA);
|
||||
// dragmsg.AddData("text/plain",
|
||||
// B_MIME_TYPE,
|
||||
// fExpression.String(),
|
||||
// fExpression.Length());
|
||||
//
|
||||
// // initiate drag & drop
|
||||
// SetFontSize(sizeDisp * K_FONT_YPROP);
|
||||
// float left = fWidth;
|
||||
// float textWidth = StringWidth(fExpression.String());
|
||||
// if (textWidth < fWidth)
|
||||
// left -= textWidth;
|
||||
// else
|
||||
// left = 0;
|
||||
// BRect displayRect(left, 0.0, fWidth, sizeDisp);
|
||||
// DragMessage(&dragmsg, displayRect);
|
||||
// }
|
||||
} else {
|
||||
// click on keypad
|
||||
|
||||
@ -407,7 +401,7 @@ CalcView::KeyDown(const char *bytes, int32 numBytes)
|
||||
|
||||
case B_SPACE:
|
||||
case B_ESCAPE:
|
||||
case 'c': // hack!
|
||||
case 'c':
|
||||
// translate to clear key
|
||||
_PressKey("C");
|
||||
break;
|
||||
@ -426,7 +420,7 @@ CalcView::KeyDown(const char *bytes, int32 numBytes)
|
||||
default: {
|
||||
// scan the keymap array for match
|
||||
int keys = fRows * fColums;
|
||||
for (int i=0; i<keys; i++) {
|
||||
for (int i = 0; i < keys; i++) {
|
||||
if (fKeypad[i].keymap[0] == bytes[0]) {
|
||||
_PressKey(i);
|
||||
return;
|
||||
@ -450,8 +444,8 @@ CalcView::MakeFocus(bool focused)
|
||||
}
|
||||
}
|
||||
|
||||
// pass on request to parent
|
||||
BView::MakeFocus(focused);
|
||||
// pass on request to text view
|
||||
fExpressionTextView->MakeFocus(focused);
|
||||
}
|
||||
|
||||
|
||||
@ -460,6 +454,24 @@ CalcView::FrameResized(float width, float height)
|
||||
{
|
||||
fWidth = width;
|
||||
fHeight = height;
|
||||
|
||||
// layout expression text view
|
||||
BRect frame = _ExpressionRect();
|
||||
fExpressionTextView->MoveTo(frame.LeftTop());
|
||||
fExpressionTextView->ResizeTo(frame.Width(), frame.Height());
|
||||
|
||||
frame.OffsetTo(B_ORIGIN);
|
||||
frame.InsetBy(2, 2);
|
||||
fExpressionTextView->SetTextRect(frame);
|
||||
|
||||
// configure expression text view font size and color
|
||||
float sizeDisp = fShowKeypad ? fHeight * K_DISPLAY_YPROP : fHeight;
|
||||
BFont font(be_bold_font);
|
||||
font.SetSize(sizeDisp * K_FONT_YPROP);
|
||||
fExpressionTextView->SetViewColor(fExpressionBGColor);
|
||||
fExpressionTextView->SetLowColor(fExpressionBGColor);
|
||||
fExpressionTextView->SetFontAndColor(&font, B_FONT_ALL, &fExpressionTextColor);
|
||||
// fExpressionTextView->SetAlignment(B_ALIGN_RIGHT);
|
||||
}
|
||||
|
||||
|
||||
@ -478,9 +490,12 @@ CalcView::AboutRequested()
|
||||
status_t
|
||||
CalcView::Archive(BMessage* archive, bool deep) const
|
||||
{
|
||||
fExpressionTextView->RemoveSelf();
|
||||
|
||||
// passed on request to parent
|
||||
status_t ret = BView::Archive(archive, deep);
|
||||
|
||||
const_cast<CalcView*>(this)->AddChild(fExpressionTextView);
|
||||
|
||||
// save app signature for replicant add-on loading
|
||||
if (ret == B_OK)
|
||||
@ -502,9 +517,7 @@ void
|
||||
CalcView::Cut()
|
||||
{
|
||||
Copy(); // copy data to clipboard
|
||||
fExpression.SetTo(""); // remove data
|
||||
|
||||
_InvalidateExpression();
|
||||
fExpressionTextView->Clear(); // remove data
|
||||
}
|
||||
|
||||
|
||||
@ -517,10 +530,11 @@ CalcView::Copy()
|
||||
BMessage *clipper = be_clipboard->Data();
|
||||
clipper->what = B_MIME_DATA;
|
||||
// TODO: should check return for errors!
|
||||
BString expression = fExpressionTextView->Text();
|
||||
clipper->AddData("text/plain",
|
||||
B_MIME_TYPE,
|
||||
fExpression.String(),
|
||||
fExpression.Length());
|
||||
expression.String(),
|
||||
expression.Length());
|
||||
//clipper->PrintToStream();
|
||||
be_clipboard->Commit();
|
||||
be_clipboard->Unlock();
|
||||
@ -564,8 +578,9 @@ CalcView::Paste(BMessage *message)
|
||||
B_MIME_TYPE,
|
||||
(const void**)&text,
|
||||
&numBytes) == B_OK) {
|
||||
fExpression.Append(text, numBytes);
|
||||
_InvalidateExpression();
|
||||
BString temp;
|
||||
temp.Append(text, numBytes);
|
||||
fExpressionTextView->Insert(temp.String());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -614,14 +629,7 @@ CalcView::LoadSettings(BMessage* archive)
|
||||
}
|
||||
|
||||
// load options
|
||||
const CalcOptions* options;
|
||||
if (archive->FindData("options", B_RAW_TYPE,
|
||||
(const void**)&options, &size) == B_OK
|
||||
&& size == sizeof(CalcOptions)) {
|
||||
memcpy(fOptions, options, size);
|
||||
} else {
|
||||
puts("Missing options from CalcView archive.\n");
|
||||
}
|
||||
fOptions->LoadSettings(archive);
|
||||
|
||||
// load option window frame
|
||||
BRect frame;
|
||||
@ -634,7 +642,7 @@ CalcView::LoadSettings(BMessage* archive)
|
||||
puts("Missing display text from CalcView archive.\n");
|
||||
} else {
|
||||
// init expression text
|
||||
fExpression = display;
|
||||
fExpressionTextView->SetText(display);
|
||||
}
|
||||
|
||||
// parse calculator description
|
||||
@ -668,8 +676,7 @@ CalcView::SaveSettings(BMessage* archive) const
|
||||
|
||||
// record current options
|
||||
if (ret == B_OK)
|
||||
ret = archive->AddData("options", B_RAW_TYPE,
|
||||
fOptions, sizeof(CalcOptions));
|
||||
ret = fOptions->SaveSettings(archive);
|
||||
|
||||
// record option window frame
|
||||
if (ret == B_OK)
|
||||
@ -677,7 +684,7 @@ CalcView::SaveSettings(BMessage* archive) const
|
||||
|
||||
// record display text
|
||||
if (ret == B_OK)
|
||||
ret = archive->AddString("displayText", fExpression.String());
|
||||
ret = archive->AddString("displayText", fExpressionTextView->Text());
|
||||
|
||||
// record calculator description
|
||||
if (ret == B_OK)
|
||||
@ -687,6 +694,92 @@ CalcView::SaveSettings(BMessage* archive) const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::Evaluate()
|
||||
{
|
||||
const double EXP_SWITCH_HI = 1e12; // # digits to switch from std->exp form
|
||||
const double EXP_SWITCH_LO = 1e-12;
|
||||
|
||||
BString expression = fExpressionTextView->Text();
|
||||
expression << "\n";
|
||||
|
||||
if (expression.Length() == 0) {
|
||||
beep();
|
||||
return;
|
||||
}
|
||||
|
||||
// audio feedback
|
||||
if (fOptions->audio_feedback) {
|
||||
BEntry zimp("zimp.AIFF");
|
||||
entry_ref zimp_ref;
|
||||
zimp.GetRef(&zimp_ref);
|
||||
play_sound(&zimp_ref, true, false, false);
|
||||
}
|
||||
|
||||
//printf("evaluate: %s\n", expression.String());
|
||||
|
||||
// evaluate expression
|
||||
Expression parser;
|
||||
|
||||
char* tmpstr = strdup(expression.String());
|
||||
char* start = tmpstr;
|
||||
char* end = start + expression.Length() - 1;
|
||||
double value = 0.0;
|
||||
|
||||
try {
|
||||
value = parser.Evaluate(start, end, true);
|
||||
} catch (const char* error) {
|
||||
fExpressionTextView->SetText(error);
|
||||
return;
|
||||
}
|
||||
|
||||
free(tmpstr);
|
||||
|
||||
//printf(" -> value: %f\n", value);
|
||||
|
||||
// beautify the expression
|
||||
// TODO: see if this is necessary at all
|
||||
char buf[64];
|
||||
if (value == 0) {
|
||||
strcpy(buf, "0");
|
||||
} else if (((value < EXP_SWITCH_HI) && (value > EXP_SWITCH_LO)) ||
|
||||
((value > -EXP_SWITCH_HI) && (value < -EXP_SWITCH_LO))) {
|
||||
// print in std form
|
||||
sprintf(buf, "%9f", value);
|
||||
|
||||
// hack to remove surplus zeros!
|
||||
if (strchr(buf, '.')) {
|
||||
int32 i = strlen(buf) - 1;
|
||||
for (; i > 0; i--) {
|
||||
if (buf[i] == '0')
|
||||
buf[i] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (buf[i] == '.')
|
||||
buf[i] = '\0';
|
||||
}
|
||||
} else {
|
||||
// print in exponential form
|
||||
sprintf(buf, "%e", value);
|
||||
}
|
||||
|
||||
// render new result to display
|
||||
fExpressionTextView->SetExpression(buf);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::FlashKey(const char* bytes, int32 numBytes)
|
||||
{
|
||||
BString temp;
|
||||
temp.Append(bytes, numBytes);
|
||||
int32 key = _KeyForLabel(temp.String());
|
||||
if (key >= 0)
|
||||
_FlashKey(key);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -697,37 +790,37 @@ CalcView::_ParseCalcDesc(const char* keypadDescription)
|
||||
fKeypad = new CalcKey[fRows * fColums];
|
||||
|
||||
// scan through calculator description and assemble keypad
|
||||
bool scanFlag = true;
|
||||
CalcKey *key = fKeypad;
|
||||
const char *p = keypadDescription;
|
||||
while (scanFlag) {
|
||||
|
||||
while (*p != 0) {
|
||||
// copy label
|
||||
char *l = key->label;
|
||||
while (!isspace(*p))
|
||||
*l++ = *p++;
|
||||
*l = '\0';
|
||||
|
||||
|
||||
// set code
|
||||
if (strcmp(key->label, "=") == 0)
|
||||
strcpy(key->code, "\n");
|
||||
else
|
||||
strcpy(key->code, key->label);
|
||||
|
||||
|
||||
// set keymap
|
||||
if (strlen(key->label)==1) {
|
||||
if (strlen(key->label) == 1) {
|
||||
strcpy(key->keymap, key->label);
|
||||
} else {
|
||||
*key->keymap = '\0';
|
||||
} // end if
|
||||
|
||||
|
||||
// add this to the expression text view, so that it
|
||||
// will forward the respective KeyDown event to us
|
||||
fExpressionTextView->AddKeypadLabel(key->label);
|
||||
|
||||
// advance
|
||||
while (isspace(*p))
|
||||
++p;
|
||||
key++;
|
||||
|
||||
// check desc termination
|
||||
if (*p == '\0')
|
||||
scanFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -740,24 +833,18 @@ CalcView::_PressKey(int key)
|
||||
|
||||
// check for backspace
|
||||
if (strcmp(fKeypad[key].label, "BS") == 0) {
|
||||
int32 length = fExpression.Length();
|
||||
if (length > 0) {
|
||||
fExpression.Remove(length - 1, 1);
|
||||
} else {
|
||||
beep();
|
||||
return; // no need to redraw
|
||||
}
|
||||
fExpressionTextView->BackSpace();
|
||||
} else if (strcmp(fKeypad[key].label, "C") == 0) {
|
||||
// C means clear
|
||||
fExpression.SetTo("");
|
||||
fExpressionTextView->Clear();
|
||||
} else {
|
||||
// append to display text
|
||||
fExpression.Append(fKeypad[key].code);
|
||||
|
||||
// check for evaluation order
|
||||
if (fKeypad[key].code[0] == '\n') {
|
||||
_Evaluate();
|
||||
Evaluate();
|
||||
} else {
|
||||
// insert into expression text
|
||||
fExpressionTextView->Insert(fKeypad[key].code);
|
||||
|
||||
// audio feedback
|
||||
if (fOptions->audio_feedback) {
|
||||
BEntry zimp("key.AIFF");
|
||||
@ -769,20 +856,36 @@ CalcView::_PressKey(int key)
|
||||
}
|
||||
|
||||
// redraw display
|
||||
_InvalidateExpression();
|
||||
// _InvalidateExpression();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::_PressKey(char *label)
|
||||
CalcView::_PressKey(const char *label)
|
||||
{
|
||||
int32 key = _KeyForLabel(label);
|
||||
if (key >= 0)
|
||||
_PressKey(key);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
CalcView::_KeyForLabel(const char *label) const
|
||||
{
|
||||
int keys = fRows * fColums;
|
||||
for (int i = 0; i < keys; i++) {
|
||||
if (strcmp(fKeypad[i].label, label) == 0) {
|
||||
_PressKey(i);
|
||||
return;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::_FlashKey(int32 key)
|
||||
{
|
||||
// TODO ...
|
||||
}
|
||||
|
||||
|
||||
@ -799,83 +902,21 @@ CalcView::_Colorize()
|
||||
fDarkColor.green = (uint8)(fBaseColor.green * 0.75);
|
||||
fDarkColor.blue = (uint8)(fBaseColor.blue * 0.75);
|
||||
fDarkColor.alpha = 255;
|
||||
}
|
||||
|
||||
// keypad text color
|
||||
uint8 lightness = (fBaseColor.red + fBaseColor.green + fBaseColor.blue) / 3;
|
||||
if (lightness > 200)
|
||||
fButtonTextColor = (rgb_color){ 0, 0, 0, 255 };
|
||||
else
|
||||
fButtonTextColor = (rgb_color){ 255, 255, 255, 255 };
|
||||
|
||||
void
|
||||
CalcView::_Evaluate()
|
||||
{
|
||||
const double EXP_SWITCH_HI = 1e12; // # digits to switch from std->exp form
|
||||
const double EXP_SWITCH_LO = 1e-12;
|
||||
|
||||
if (fExpression.Length() == 0) {
|
||||
beep();
|
||||
return;
|
||||
}
|
||||
|
||||
// audio feedback
|
||||
if (fOptions->audio_feedback) {
|
||||
BEntry zimp("zimp.AIFF");
|
||||
entry_ref zimp_ref;
|
||||
zimp.GetRef(&zimp_ref);
|
||||
play_sound(&zimp_ref, true, false, false);
|
||||
}
|
||||
|
||||
//printf("evaluate: %s\n", fExpression.String());
|
||||
|
||||
// evaluate expression
|
||||
Expression parser;
|
||||
|
||||
char* tmpstr = strdup(fExpression.String());
|
||||
char* start = tmpstr;
|
||||
char* end = start + fExpression.Length() - 1;
|
||||
double value = 0.0;
|
||||
|
||||
try {
|
||||
value = parser.Eval(start, end, true);
|
||||
|
||||
} catch (const char* error) {
|
||||
fExpression = error;
|
||||
_InvalidateExpression();
|
||||
return;
|
||||
}
|
||||
|
||||
free(tmpstr);
|
||||
|
||||
//printf(" -> value: %f\n", value);
|
||||
|
||||
// beautify the expression
|
||||
// TODO: see if this is necessary at all
|
||||
char buf[64];
|
||||
if (value == 0) {
|
||||
strcpy(buf, "0");
|
||||
} else if (((value < EXP_SWITCH_HI) && (value > EXP_SWITCH_LO)) ||
|
||||
((value > -EXP_SWITCH_HI) && (value < -EXP_SWITCH_LO))) {
|
||||
// print in std form
|
||||
sprintf(buf, "%9lf", value);
|
||||
|
||||
// hack to remove surplus zeros!
|
||||
if (strchr(buf, '.')) {
|
||||
int32 i = strlen(buf) - 1;
|
||||
for (; i > 0; i--) {
|
||||
if (buf[i] == '0')
|
||||
buf[i] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (buf[i] == '.')
|
||||
buf[i] = '\0';
|
||||
}
|
||||
} else {
|
||||
// print in exponential form
|
||||
sprintf(buf, "%le", value);
|
||||
}
|
||||
|
||||
// render new result to display
|
||||
fExpression = buf;
|
||||
|
||||
// redraw display
|
||||
_InvalidateExpression();
|
||||
// expression text color
|
||||
lightness = (fExpressionBGColor.red +
|
||||
fExpressionBGColor.green + fExpressionBGColor.blue) / 3;
|
||||
if (lightness > 200)
|
||||
fExpressionTextColor = (rgb_color){ 0, 0, 0, 255 };
|
||||
else
|
||||
fExpressionTextColor = (rgb_color){ 255, 255, 255, 255 };
|
||||
}
|
||||
|
||||
|
||||
@ -895,11 +936,47 @@ CalcView::_CreatePopUpMenu()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::_InvalidateExpression()
|
||||
BRect
|
||||
CalcView::_ExpressionRect() const
|
||||
{
|
||||
float sizeDisp = fHeight * K_DISPLAY_YPROP;
|
||||
BRect displayRect(0.0, 0.0, fWidth, sizeDisp);
|
||||
Invalidate(displayRect);
|
||||
BRect r(0.0, 0.0, fWidth, fHeight);
|
||||
if (fShowKeypad) {
|
||||
r.bottom = floorf(fHeight * K_DISPLAY_YPROP);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
CalcView::_KeypadRect() const
|
||||
{
|
||||
BRect r(0.0, 0.0, -1.0, -1.0);
|
||||
if (fShowKeypad) {
|
||||
r.right = fWidth;
|
||||
r.bottom = fHeight;
|
||||
r.top = floorf(fHeight * K_DISPLAY_YPROP) + 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CalcView::_ShowKeypad(bool show)
|
||||
{
|
||||
if (fShowKeypad == show)
|
||||
return;
|
||||
|
||||
fShowKeypad = show;
|
||||
|
||||
float height = fShowKeypad ? fHeight / K_DISPLAY_YPROP
|
||||
: fHeight * K_DISPLAY_YPROP;
|
||||
|
||||
BWindow* window = Window();
|
||||
if (window->Bounds() == Frame())
|
||||
window->ResizeTo(fWidth, height);
|
||||
else
|
||||
ResizeTo(fWidth, height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -12,12 +12,12 @@
|
||||
#define _CALC_VIEW_H
|
||||
|
||||
#include <View.h>
|
||||
#include <String.h>
|
||||
|
||||
class BString;
|
||||
class BMenuItem;
|
||||
class CalcOptions;
|
||||
class CalcOptionsWindow;
|
||||
class ExpressionTextView;
|
||||
|
||||
_EXPORT
|
||||
class CalcView : public BView {
|
||||
@ -33,7 +33,7 @@ class CalcView : public BView {
|
||||
|
||||
virtual ~CalcView();
|
||||
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void MouseDown(BPoint point);
|
||||
@ -60,18 +60,30 @@ class CalcView : public BView {
|
||||
status_t LoadSettings(BMessage* archive);
|
||||
status_t SaveSettings(BMessage* archive) const;
|
||||
|
||||
void Evaluate();
|
||||
|
||||
void FlashKey(const char* bytes, int32 numBytes);
|
||||
|
||||
void AddExpressionToHistory(const char* expression);
|
||||
void PreviousExpression();
|
||||
void NextExpression();
|
||||
|
||||
private:
|
||||
void _ParseCalcDesc(const char* keypadDescription);
|
||||
|
||||
void _PressKey(int key);
|
||||
void _PressKey(char* label);
|
||||
void _PressKey(const char* label);
|
||||
int32 _KeyForLabel(const char* label) const;
|
||||
void _FlashKey(int32 key);
|
||||
|
||||
void _Colorize();
|
||||
|
||||
void _Evaluate();
|
||||
|
||||
void _CreatePopUpMenu();
|
||||
void _InvalidateExpression();
|
||||
|
||||
BRect _ExpressionRect() const;
|
||||
BRect _KeypadRect() const;
|
||||
|
||||
void _ShowKeypad(bool show);
|
||||
|
||||
// grid dimensions
|
||||
int16 fColums;
|
||||
@ -81,7 +93,9 @@ class CalcView : public BView {
|
||||
rgb_color fBaseColor;
|
||||
rgb_color fLightColor;
|
||||
rgb_color fDarkColor;
|
||||
rgb_color fButtonTextColor;
|
||||
rgb_color fExpressionBGColor;
|
||||
rgb_color fExpressionTextColor;
|
||||
|
||||
// view dimensions
|
||||
float fWidth;
|
||||
@ -93,8 +107,8 @@ class CalcView : public BView {
|
||||
char* fKeypadDescription;
|
||||
CalcKey* fKeypad;
|
||||
|
||||
// display text
|
||||
BString fExpression;
|
||||
// expression
|
||||
ExpressionTextView* fExpressionTextView;
|
||||
|
||||
// pop-up context menu.
|
||||
BMenuItem* fAboutItem;
|
||||
@ -105,6 +119,7 @@ class CalcView : public BView {
|
||||
CalcOptions* fOptions;
|
||||
CalcOptionsWindow* fOptionsWindow;
|
||||
BRect fOptionsWindowFrame;
|
||||
bool fShowKeypad;
|
||||
};
|
||||
|
||||
#endif // _CALC_VIEW_H
|
||||
|
212
src/apps/deskcalc/ExpressionTextView.cpp
Normal file
212
src/apps/deskcalc/ExpressionTextView.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2006 Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*/
|
||||
|
||||
#include "ExpressionTextView.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <Beep.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "CalcView.h"
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
static const int32 kMaxPreviousExpressions = 20;
|
||||
|
||||
|
||||
ExpressionTextView::ExpressionTextView(BRect frame, CalcView* calcView)
|
||||
: InputTextView(frame, "expression text view",
|
||||
(frame.OffsetToCopy(B_ORIGIN)).InsetByCopy(2, 2),
|
||||
B_FOLLOW_NONE, B_WILL_DRAW),
|
||||
fCalcView(calcView),
|
||||
fKeypadLabels(""),
|
||||
fPreviousExpressions(20)
|
||||
{
|
||||
SetFont(be_bold_font);
|
||||
// SetAlignment(B_ALIGN_RIGHT);
|
||||
SetStylable(false);
|
||||
SetDoesUndo(true);
|
||||
SetColorSpace(B_RGB32);
|
||||
}
|
||||
|
||||
|
||||
ExpressionTextView::~ExpressionTextView()
|
||||
{
|
||||
int32 count = fPreviousExpressions.CountItems();
|
||||
for (int32 i = 0; i < count; i++)
|
||||
delete (BString*)fPreviousExpressions.ItemAtFast(i);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::MakeFocus(bool focused = true)
|
||||
{
|
||||
if (focused == IsFocus()) {
|
||||
// stop endless loop when CalcView calls us again
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: order of lines important!
|
||||
InputTextView::MakeFocus(focused);
|
||||
fCalcView->MakeFocus(focused);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::KeyDown(const char* bytes, int32 numBytes)
|
||||
{
|
||||
// handle expression history
|
||||
if (bytes[0] == B_UP_ARROW) {
|
||||
PreviousExpression();
|
||||
return;
|
||||
}
|
||||
if (bytes[0] == B_DOWN_ARROW) {
|
||||
NextExpression();
|
||||
return;
|
||||
}
|
||||
|
||||
// handle in InputTextView, except B_TAB
|
||||
if (bytes[0] != B_TAB)
|
||||
InputTextView::KeyDown(bytes, numBytes);
|
||||
|
||||
// pass on to CalcView if this was a label on a key
|
||||
if (fKeypadLabels.FindFirst(bytes[0]) >= 0)
|
||||
fCalcView->FlashKey(bytes, numBytes);
|
||||
|
||||
// as soon as something is typed, we are at the
|
||||
// end of the expression history
|
||||
fHistoryPos = fPreviousExpressions.CountItems();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::MouseDown(BPoint where)
|
||||
{
|
||||
uint32 buttons;
|
||||
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
|
||||
if (buttons & B_PRIMARY_MOUSE_BUTTON) {
|
||||
InputTextView::MouseDown(where);
|
||||
return;
|
||||
}
|
||||
where = ConvertToParent(where);
|
||||
fCalcView->MouseDown(where);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::RevertChanges()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::ApplyChanges()
|
||||
{
|
||||
AddExpressionToHistory(Text());
|
||||
fCalcView->Evaluate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::AddKeypadLabel(const char* label)
|
||||
{
|
||||
fKeypadLabels << label;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::SetExpression(const char* expression)
|
||||
{
|
||||
SetText(expression);
|
||||
int32 lastPos = strlen(expression);
|
||||
Select(lastPos, lastPos);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::BackSpace()
|
||||
{
|
||||
if (Window())
|
||||
Window()->PostMessage(B_UNDO, this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::Clear()
|
||||
{
|
||||
SetText("");
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::AddExpressionToHistory(const char* expression)
|
||||
{
|
||||
BString* item = new (nothrow) BString(expression);
|
||||
if (!item)
|
||||
return;
|
||||
if (!fPreviousExpressions.AddItem(item)) {
|
||||
delete item;
|
||||
return;
|
||||
}
|
||||
while (fPreviousExpressions.CountItems() > kMaxPreviousExpressions)
|
||||
delete (BString*)fPreviousExpressions.RemoveItem(0L);
|
||||
|
||||
fHistoryPos = fPreviousExpressions.CountItems();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::PreviousExpression()
|
||||
{
|
||||
int32 count = fPreviousExpressions.CountItems();
|
||||
if (fHistoryPos == count) {
|
||||
// save current expression
|
||||
fCurrentExpression = Text();
|
||||
}
|
||||
|
||||
fHistoryPos--;
|
||||
if (fHistoryPos < 0) {
|
||||
fHistoryPos = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
BString* item = (BString*)fPreviousExpressions.ItemAt(fHistoryPos);
|
||||
if (item)
|
||||
SetExpression(item->String());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionTextView::NextExpression()
|
||||
{
|
||||
int32 count = fPreviousExpressions.CountItems();
|
||||
|
||||
fHistoryPos++;
|
||||
if (fHistoryPos == count) {
|
||||
SetExpression(fCurrentExpression.String());
|
||||
return;
|
||||
}
|
||||
|
||||
if (fHistoryPos > count) {
|
||||
fHistoryPos = count;
|
||||
return;
|
||||
}
|
||||
|
||||
BString* item = (BString*)fPreviousExpressions.ItemAt(fHistoryPos);
|
||||
if (item)
|
||||
SetExpression(item->String());
|
||||
}
|
||||
|
BIN
src/apps/deskcalc/ExpressionTextView.h
Normal file
BIN
src/apps/deskcalc/ExpressionTextView.h
Normal file
Binary file not shown.
163
src/apps/deskcalc/InputTextView.cpp
Normal file
163
src/apps/deskcalc/InputTextView.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2006 Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*/
|
||||
|
||||
#include "InputTextView.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <String.h>
|
||||
|
||||
// constructor
|
||||
InputTextView::InputTextView(BRect frame, const char* name,
|
||||
BRect textRect,
|
||||
uint32 resizingMode,
|
||||
uint32 flags)
|
||||
: BTextView(frame, name, textRect, resizingMode, flags),
|
||||
fWasFocus(false)
|
||||
{
|
||||
SetWordWrap(false);
|
||||
}
|
||||
|
||||
// destructor
|
||||
InputTextView::~InputTextView()
|
||||
{
|
||||
}
|
||||
|
||||
// MouseDown
|
||||
void
|
||||
InputTextView::MouseDown(BPoint where)
|
||||
{
|
||||
// enforce the behaviour of a typical BTextControl
|
||||
// only let the BTextView handle mouse up/down when
|
||||
// it already had focus
|
||||
fWasFocus = IsFocus();
|
||||
if (fWasFocus) {
|
||||
BTextView::MouseDown(where);
|
||||
} else {
|
||||
// forward click
|
||||
if (BView* view = Parent()) {
|
||||
view->MouseDown(ConvertToParent(where));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MouseUp
|
||||
void
|
||||
InputTextView::MouseUp(BPoint where)
|
||||
{
|
||||
// enforce the behaviour of a typical BTextControl
|
||||
// only let the BTextView handle mouse up/down when
|
||||
// it already had focus
|
||||
if (fWasFocus)
|
||||
BTextView::MouseUp(where);
|
||||
}
|
||||
|
||||
// KeyDown
|
||||
void
|
||||
InputTextView::KeyDown(const char* bytes, int32 numBytes)
|
||||
{
|
||||
bool handled = true;
|
||||
if (numBytes > 0) {
|
||||
switch (bytes[0]) {
|
||||
case B_ESCAPE:
|
||||
// revert any typing changes
|
||||
RevertChanges();
|
||||
break;
|
||||
case B_TAB:
|
||||
// skip BTextView implementation
|
||||
BView::KeyDown(bytes, numBytes);
|
||||
// fall through
|
||||
case B_RETURN:
|
||||
ApplyChanges();
|
||||
break;
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!handled)
|
||||
BTextView::KeyDown(bytes, numBytes);
|
||||
}
|
||||
|
||||
// MakeFocus
|
||||
void
|
||||
InputTextView::MakeFocus(bool focus)
|
||||
{
|
||||
if (focus != IsFocus()) {
|
||||
if (BView* view = Parent())
|
||||
view->Invalidate();
|
||||
BTextView::MakeFocus(focus);
|
||||
if (focus)
|
||||
SelectAll();
|
||||
ApplyChanges();
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke
|
||||
status_t
|
||||
InputTextView::Invoke(BMessage* message)
|
||||
{
|
||||
if (!message)
|
||||
message = Message();
|
||||
|
||||
if (message) {
|
||||
BMessage copy(*message);
|
||||
copy.AddInt64("when", system_time());
|
||||
copy.AddPointer("source", (BView*)this);
|
||||
return BInvoker::Invoke(©);
|
||||
}
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// Select
|
||||
void
|
||||
InputTextView::Select(int32 start, int32 finish)
|
||||
{
|
||||
BTextView::Select(start, finish);
|
||||
|
||||
_CheckTextRect();
|
||||
}
|
||||
|
||||
// InsertText
|
||||
void
|
||||
InputTextView::InsertText(const char* inText, int32 inLength, int32 inOffset,
|
||||
const text_run_array* inRuns)
|
||||
{
|
||||
BTextView::InsertText(inText, inLength, inOffset, inRuns);
|
||||
|
||||
_CheckTextRect();
|
||||
}
|
||||
|
||||
// DeleteText
|
||||
void
|
||||
InputTextView::DeleteText(int32 fromOffset, int32 toOffset)
|
||||
{
|
||||
BTextView::DeleteText(fromOffset, toOffset);
|
||||
|
||||
_CheckTextRect();
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _CheckTextRect
|
||||
void
|
||||
InputTextView::_CheckTextRect()
|
||||
{
|
||||
// update text rect and make sure
|
||||
// the cursor/selection is in view
|
||||
BRect textRect(TextRect());
|
||||
float width = ceilf(StringWidth(Text()) + 2.0);
|
||||
if (textRect.Width() < width) {
|
||||
textRect.right = textRect.left + width;
|
||||
SetTextRect(textRect);
|
||||
ScrollToSelection();
|
||||
}
|
||||
}
|
57
src/apps/deskcalc/InputTextView.h
Normal file
57
src/apps/deskcalc/InputTextView.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2006 Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*/
|
||||
|
||||
#ifndef INPUT_TEXT_VIEW_H
|
||||
#define INPUT_TEXT_VIEW_H
|
||||
|
||||
#include <Invoker.h>
|
||||
#include <TextView.h>
|
||||
|
||||
class InputTextView : public BTextView,
|
||||
public BInvoker {
|
||||
public:
|
||||
InputTextView(BRect frame,
|
||||
const char* name,
|
||||
BRect textRect,
|
||||
uint32 resizingMode,
|
||||
uint32 flags);
|
||||
virtual ~InputTextView();
|
||||
|
||||
// BTextView interface
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
|
||||
virtual void KeyDown(const char* bytes, int32 numBytes);
|
||||
virtual void MakeFocus(bool focus);
|
||||
|
||||
// BInvoker interface
|
||||
virtual status_t Invoke(BMessage* message = NULL);
|
||||
|
||||
// InputTextView
|
||||
virtual void RevertChanges() = 0;
|
||||
virtual void ApplyChanges() = 0;
|
||||
|
||||
protected:
|
||||
// BTextView
|
||||
virtual void Select(int32 start, int32 finish);
|
||||
|
||||
virtual void InsertText(const char* inText,
|
||||
int32 inLength,
|
||||
int32 inOffset,
|
||||
const text_run_array* inRuns);
|
||||
virtual void DeleteText(int32 fromOffset,
|
||||
int32 toOffset);
|
||||
|
||||
void _CheckTextRect();
|
||||
|
||||
bool fWasFocus;
|
||||
};
|
||||
|
||||
#endif // INPUT_TEXT_VIEW_H
|
||||
|
||||
|
@ -10,6 +10,8 @@ Application DeskCalc :
|
||||
CalcView.cpp
|
||||
CalcWindow.cpp
|
||||
DeskCalc.cpp
|
||||
ExpressionTextView.cpp
|
||||
InputTextView.cpp
|
||||
Parser.cpp
|
||||
: be $(TARGET_LIBSTDC++) media
|
||||
: DeskCalc.rdef
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,31 +40,30 @@
|
||||
|
||||
class Expression {
|
||||
public:
|
||||
static double valtod(const char *exp, const char **end);
|
||||
static double exptod(const char *exp, const char **end);
|
||||
static std::string dtostr(const double value, const unsigned int precision, const char mode); // 0 => exp, 1 => exp3, 2 => SI
|
||||
static int strprintf(std::string &str, const char * format, ...);
|
||||
Expression();
|
||||
|
||||
Expression();
|
||||
void SetAglf(const double value);
|
||||
bool SetConstant(const char* name,
|
||||
const double value);
|
||||
|
||||
void SetAglf(const double value);
|
||||
bool SetConstant(const char *name, const double value);
|
||||
|
||||
double Eval(const char *exp);
|
||||
double Eval(const char *begin, const char *end, const bool allowWhiteSpaces = false);
|
||||
const char *Error();
|
||||
double Evaluate(const char* exp);
|
||||
double Evaluate(const char* begin, const char* end,
|
||||
const bool allowWhiteSpaces = false);
|
||||
const char* Error();
|
||||
|
||||
private:
|
||||
double m_aglf;
|
||||
const char *m_errorPtr;
|
||||
bool m_trig;
|
||||
double _ApplyFunction(const double x,
|
||||
const size_t number) const;
|
||||
|
||||
double func(const double x, const size_t number) const;
|
||||
std::vector<std::string> m_functionNames;
|
||||
std::vector<char> m_functionTypes;
|
||||
double fAglf;
|
||||
const char* fErrorPtr;
|
||||
bool fTrig;
|
||||
|
||||
std::vector<std::string> m_constantNames;
|
||||
std::vector<double> m_constantValues;
|
||||
std::vector<std::string> fFunctionNames;
|
||||
std::vector<char> fFunctionTypes;
|
||||
|
||||
std::vector<std::string> fConstantNames;
|
||||
std::vector<double> fConstantValues;
|
||||
};
|
||||
|
||||
#endif // PARSER_H
|
||||
|
Loading…
Reference in New Issue
Block a user