Initial checkin with some style cleanups from original sources

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17681 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm 2006-05-31 21:43:25 +00:00
parent a7b537b877
commit 0d960ff17f
14 changed files with 1642 additions and 0 deletions

View File

@ -0,0 +1,349 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#include "CalcEngine.h"
#include <string.h>
#include <Beep.h>
CalcEngine::CalcEngine(int max_digits_in)
{
max_digits = max_digits_in;
Clear();
}
void CalcEngine::Clear()
{
trig_inverse_active = false;
trig_is_radians = false;
already_have_infix = false;
number_stack_index = 0;
symbol_stack_index = 0;
keyed_value = 0.0;
text[0] = '\0';
}
CalcEngine::~CalcEngine()
{
}
double CalcEngine::GetValue(char *str)
{
if (strlen(text) == 0)
{
if (str != NULL)
{
int precision = max_digits+1;
char format[10];
do
{
precision--;
sprintf(format, "%%.%dg", precision);
sprintf(str, format, keyed_value);
} while (!TextWidthOK(str));
}
return keyed_value;
}
else
{
if (str != NULL)
strcpy(str, text);
return atof(text);
}
}
bool CalcEngine::TextWidthOK(const char *str)
{
return (int)strlen(str) < max_digits+1 ? true : false;
}
void CalcEngine::DoCommand(ulong what)
{
bool is_infix_symbol = false;
int i;
double d;
switch (what)
{
case 'clr':
if (keyed_value == 0 && strlen(text)==0)
{
// Clear was just pressed before, so reset everything.
Clear();
}
SetValue(0.0);
break;
case '¹':
case 'p':
case 'pi':
SetValue(M_PI);
break;
case 'e':
SetValue(M_E);
break;
case '-/+':
if (strlen(text)==0) keyed_value = -keyed_value;
else
{
// Must stick a minus sign in front of the text or
// after 'e' in exponential form.
char *p = strchr(text, 'e');
if (p == NULL) p = text;
else p += 1; // one char after 'e'
// p now points to insertion point
if (p[0] == '-')
p[0] = '+';
else if (p[0] == '+')
p[0] = '-';
else
{
memmove(p+1, p, strlen(p)+1);
p[0] = '-';
}
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
Append(what);
break;
case 'exp':
if (strlen(text) > 0 && strchr(text,'e')==NULL)
Append('e');
else
beep();
break;
case '.':
if (strlen(text) == 0)
SetValue("0.");
else if (strchr(text,'.')==NULL && strchr(text,'e')==NULL)
Append('.');
else beep();
break;
case '(':
PushSymbol(what);
SetValue(0.0);
break;
case ')':
PushKeyedValue();
while (symbol_stack_index > 0
&& symbol_stack[symbol_stack_index-1] != '(') // )
{
d = DoStackedCalculation();
}
if (symbol_stack_index > 0
&& symbol_stack[symbol_stack_index-1] == '(') // )
symbol_stack_index--;
SetValue(number_stack[--number_stack_index]);
break;
case '+':
case '-':
is_infix_symbol = true;
if (already_have_infix) symbol_stack_index--;
else PushKeyedValue();
d = GetValue();
while (symbol_stack_index > 0
&& (symbol_stack[symbol_stack_index-1] == '+'
|| symbol_stack[symbol_stack_index-1] == '-'
|| symbol_stack[symbol_stack_index-1] == '*'
|| symbol_stack[symbol_stack_index-1] == '/'
|| symbol_stack[symbol_stack_index-1] == '^'
|| symbol_stack[symbol_stack_index-1] == '^1/y'))
{
d = DoStackedCalculation();
}
SetValue(d);
PushSymbol(what);
break;
case '*':
case '/':
is_infix_symbol = true;
if (already_have_infix) symbol_stack_index--;
else PushKeyedValue();
d = GetValue();
while (symbol_stack_index > 0
&& (symbol_stack[symbol_stack_index-1] == '*'
|| symbol_stack[symbol_stack_index-1] == '/'
|| symbol_stack[symbol_stack_index-1] == '^'
|| symbol_stack[symbol_stack_index-1] == '^1/y'))
{
d = DoStackedCalculation();
}
SetValue(d);
PushSymbol(what);
break;
case '^':
case '^1/y':
is_infix_symbol = true;
if (already_have_infix) symbol_stack_index--;
else PushKeyedValue();
d = GetValue();
while (symbol_stack_index > 0
&& (symbol_stack[symbol_stack_index-1] == '^'
|| symbol_stack[symbol_stack_index-1] == '^1/y'))
{
d = DoStackedCalculation();
}
SetValue(d);
PushSymbol(what);
break;
case 'x^2':
d = GetValue();
SetValue(d * d);
break;
case 'sqrt':
SetValue(sqrt(GetValue()));
break;
case '10^x':
SetValue(pow(10.0, GetValue()));
break;
case 'log':
SetValue(log10(GetValue()));
break;
case 'e^x':
SetValue(exp(GetValue()));
break;
case 'ln x':
SetValue(log(GetValue()));
break;
case '1/x':
SetValue(1.0 / GetValue());
break;
case '!':
d = GetValue();
if (d > 1000) d = 1000;
else if (d < -1000) d = -1000;
if (d >= 0)
{
i = (int)(d + 0.0000000001);
d = 1.0;
}
else
{
i = (int)(-d + 0.0000000001);
d = -1.0;
}
while (i > 0)
{
d *= i;
i--;
}
SetValue(d);
break;
case 'sin':
if (trig_inverse_active)
SetValue(TrigAngleOutput(asin(GetValue())));
else
SetValue(sin(TrigAngleInput(GetValue())));
break;
case 'cos':
if (trig_inverse_active)
SetValue(TrigAngleOutput(acos(GetValue())));
else
SetValue(cos(TrigAngleInput(GetValue())));
break;
case 'tan':
if (trig_inverse_active)
SetValue(TrigAngleOutput(atan(GetValue())));
else
SetValue(tan(TrigAngleInput(GetValue())));
break;
case '=':
case 'entr':
if (already_have_infix) symbol_stack_index--;
else PushKeyedValue();
while (symbol_stack_index > 0)
{
d = DoStackedCalculation();
}
d = number_stack[--number_stack_index];
number_stack_index = 0;
SetValue(d);
break;
case 'trgA':
trig_inverse_active = !trig_inverse_active;
break;
case 'trgM':
trig_is_radians = !trig_is_radians;
break;
}
already_have_infix = is_infix_symbol;
if (what != 'trgA' && trig_inverse_active)
{
trig_inverse_active = !trig_inverse_active;
}
}
void CalcEngine::PushKeyedValue()
{
double d = GetValue();
number_stack[number_stack_index++] = d;
SetValue(d);
}
void CalcEngine::PushSymbol(ulong sym)
{
symbol_stack[symbol_stack_index++] = sym;
}
double CalcEngine::DoStackedCalculation()
{
ulong sym = symbol_stack[--symbol_stack_index];
double right_number = number_stack[--number_stack_index];
double left_number = number_stack[--number_stack_index];
double result;
switch (sym)
{
case '+':
result = left_number + right_number;
break;
case '-':
result = left_number - right_number;
break;
case '*':
result = left_number * right_number;
break;
case '/':
result = left_number / right_number;
break;
case '^':
result = pow(left_number, right_number);
break;
case '^1/y':
result = pow(left_number, 1.0/right_number);
break;
default:
// bogus !
result = 0;
break;
}
number_stack[number_stack_index++] = result;
return result;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#ifndef __CALC_ENGINE__
#define __CALC_ENGINE__
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef unsigned long ulong;
class CalcEngine
{
public:
CalcEngine(int max_digits = 12);
virtual ~CalcEngine();
void DoCommand(ulong key);
double GetValue(char *val=NULL);
void Clear(void);
bool TrigInverseActive() { return trig_inverse_active; };
bool TrigIsRadians() { return trig_is_radians; };
virtual bool TextWidthOK(const char *text);
private:
enum { max_stack_size = 20 };
enum { mode_start=0, mode_input };
char text[64];
double keyed_value;
void SetValue(double d) { keyed_value=d; text[0]='\0'; };
void SetValue(const char *str) { keyed_value=0; strcpy(text,str);};
void Append(char c) { char *p=text+strlen(text); *p++=c; *p='\0'; };
double DoStackedCalculation();
void PushKeyedValue();
void PushSymbol(ulong sym);
int max_digits;
bool trig_inverse_active;
bool trig_is_radians;
bool already_have_infix;
int number_stack_index;
double number_stack[max_stack_size];
int symbol_stack_index;
ulong symbol_stack[max_stack_size];
double TrigAngleInput(double d) { return trig_is_radians?d:M_PI/180*d; };
double TrigAngleOutput(double d) { return trig_is_radians?d:180/M_PI*d; };
};
#endif

View File

@ -0,0 +1,589 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#include <iostream.h>
#include <ctype.h>
#include <string.h>
#include <Alert.h>
#include <Button.h>
#include <StringView.h>
#include <Beep.h>
#include <Dragger.h>
#include <TextView.h>
#include <View.h>
#include <Clipboard.h>
#include "CalcView.h"
#include "FrameView.h"
const int border = 8;
const int key_border = 4;
const int key_height = 23;
const int key_width = 32;
void CalcView::MouseDown(BPoint where)
{
BView::MouseDown(where);
MakeFocus();
ChangeHighlight();
}
void CalcView::ChangeHighlight()
{
int state = state_unknown;
BWindow *wind = Window();
if (wind != NULL)
state = (wind->IsActive() && IsFocus()) ? state_active : state_inactive;
if (state != current_highlight) {
rgb_color on = {204,204,255};
rgb_color off = {204*9/10, 204*9/10, 255*9/10};
if (state == state_inactive) {
lcd_frame->SetViewColor(off);
lcd->SetLowColor(off);
lcd->SetViewColor(off);
// lcd->SetHighColor(102,102,102);
}
else {
lcd_frame->SetViewColor(on);
lcd->SetLowColor(on);
lcd->SetViewColor(on);
// lcd->SetHighColor(51,51,51);
}
lcd_frame->Invalidate();
lcd->Invalidate();
current_highlight = state;
}
}
void CalcView::WindowActivated(bool state)
{
BView::WindowActivated(state);
ChangeHighlight();
}
void CalcView::MakeFocus(bool focusState)
{
BView::MakeFocus(focusState);
ChangeHighlight();
}
CalcView::CalcView(BRect rect)
: BView(rect, "Calculator", B_FOLLOW_NONE, B_WILL_DRAW),
calc(15)
{
Init();
BDragger *dragger;
dragger = new BDragger(BRect(0,0,7,7), this, 0);
AddChild(dragger);
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BRect r;
r.left = border;
r.right = r.left + key_border*8 + key_width*7;
r.top = border-1;
r.bottom = r.top + 40;
r.InsetBy(-1,0);
lcd_frame = new FrameView(r, "lcd frame", B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP, 1);
AddChild(lcd_frame);
BRect r2;
r2 = lcd_frame->Bounds();
r2.InsetBy(5,2);
r2.OffsetBy(3,1);
lcd = new BStringView(r2, "lcd", "0", B_FOLLOW_ALL_SIDES);
lcd->SetFont(be_plain_font/*"Arial MT"*/);
lcd->SetFontSize(30);
lcd->SetAlignment(B_ALIGN_RIGHT);
lcd_frame->AddChild(lcd);
static FrameView::ClusterInfo trig_button_info[] =
{ {"sin", 'sin'}, {"cos", 'cos'},
{"tan", 'tan'}, {0}, {0},
{"inv", 'trgA'}, {"deg", 'trgM'}
};
FrameView *trig_frame
= new FrameView(BPoint(8,57), "trig area", B_FOLLOW_NONE,
7,1, 1, key_border, key_height, key_width,
trig_button_info);
AddChild(trig_frame);
static FrameView::ClusterInfo const_button_info[] =
{ {"-/+", '-/+'}, {"exp", 'exp'},
{"e", 'e'}, {"pi", 'pi'}, {0},
{"(", '('}, {")", ')'}
};
FrameView *const_frame
= new FrameView(BPoint(8,97), "const area", B_FOLLOW_NONE,
7,1, 1, key_border, key_height, key_width,
const_button_info);
AddChild(const_frame);
static FrameView::ClusterInfo keypad_button_info[] =
{ {"C",'clr'}, {"=",'='}, {"/",'/'}, {"*",'*'},
{"7",'7'}, {"8",'8'}, {"9",'9'}, {"-",'-'},
{"4",'4'}, {"5",'5'}, {"6",'6'}, {"+",'+'},
{"1",'1'}, {"2",'2'}, {"3",'3'}, {"=",'entr'},
{"0",'0'}, {0}, {".",'.'}, {0}
};
FrameView *keypad_frame
= new FrameView(BPoint(8,137), "keypad area", B_FOLLOW_NONE,
4,5, 1, key_border, key_height, key_width,
keypad_button_info);
AddChild(keypad_frame);
keypad_frame->FindView("entr")->ResizeBy(0, key_height+key_border);
keypad_frame->FindView("0")->ResizeBy(key_width+key_border, 0);
static FrameView::ClusterInfo func_button_info[] =
{ {"x^y", '^'}, {"x^1/y", '^1/y'},
{"x^2", 'x^2'}, {"sqrt", 'sqrt'},
{"10^x", '10^x'}, {"log", 'log'},
{"e^x", 'e^x'}, {"ln x", 'ln x'},
{"x!", '!'}, {"1/x", '1/x'}
};
FrameView *func_frame
= new FrameView(BPoint(188,137), "func area", B_FOLLOW_NONE,
2,5, 1, key_border, key_height, key_width,
func_button_info);
AddChild(func_frame);
}
CalcView::CalcView(BMessage *msg)
: BView(msg),
calc(15)
{
Init();
is_replicant = true;
lcd_frame = (FrameView *)FindView("lcd frame");
lcd = (BStringView *)FindView("lcd");
lcd->SetText("0");
}
void CalcView::Init()
{
is_replicant = false;
current_highlight = state_unknown;
binary_sign_view = NULL;
binary_exponent_view = NULL;
binary_number_view = NULL;
}
void CalcView::Draw(BRect updateRect)
{
BView::Draw(updateRect);
if (is_replicant)
{
const float bevel = 2;
BRect r = Bounds();
r.right -= (bevel - 1);
r.bottom -= (bevel - 1);
SetPenSize(bevel);
StrokeRect(r);
SetPenSize(1);
}
}
BView * CalcView::AddExtra()
{
BRect r2;
BRect r = Frame();
r.top = r.bottom;
r.bottom = r.top + ExtraHeight();
BView *view = new BView(r, "Calculator Extra", 0, B_WILL_DRAW);
view->SetViewColor(153,153,153);
r = view->Bounds();
r.InsetBy(border, 1);
r.left -= 1;
r.bottom = r.top + 16;
r.right = r.left + 8+2;
FrameView *binary_frame = new FrameView(r, NULL, 0, 1);
view->AddChild(binary_frame);
r2 = binary_frame->Bounds();
r2.InsetBy(2,2);
r2.OffsetBy(1,1);
binary_sign_view = new BStringView(r2, "binary sign view", "", 0);
binary_sign_view->SetAlignment(B_ALIGN_CENTER);
binary_sign_view->SetViewColor(binary_frame->ViewColor());
binary_frame->AddChild(binary_sign_view);
r.OffsetBy(r.Width()+3, 0);
r.right = r.left + 72;
binary_frame = new FrameView(r, NULL, 0, 1);
view->AddChild(binary_frame);
r2 = binary_frame->Bounds();
r2.InsetBy(2,2);
r2.OffsetBy(1,1);
binary_exponent_view = new BStringView(r2, "binary exponent view", "", 0);
binary_exponent_view->SetAlignment(B_ALIGN_CENTER);
binary_exponent_view->SetViewColor(binary_frame->ViewColor());
binary_frame->AddChild(binary_exponent_view);
r.OffsetBy(r.Width()+3, 0);
r.right = Bounds().Width() - border + 1;
binary_frame = new FrameView(r, NULL, 0, 1);
view->AddChild(binary_frame);
r2 = binary_frame->Bounds();
r2.InsetBy(2,2);
r2.OffsetBy(1,1);
binary_number_view = new BStringView(r2, "binary number view", "", 0);
binary_number_view->SetAlignment(B_ALIGN_CENTER);
binary_number_view->SetViewColor(binary_frame->ViewColor());
binary_frame->AddChild(binary_number_view);
r = view->Bounds();
r.InsetBy(border, 0);
r.top = binary_frame->Frame().bottom + 3;
r.bottom = r.top + 16;
r.InsetBy(-1,0);
FrameView *about_frame = new FrameView(r, NULL, 0, 1);
view->AddChild(about_frame);
r2 = about_frame->Bounds();
r2.InsetBy(2,2);
r2.OffsetBy(0,1);
BStringView *peter = new BStringView(r2, NULL,
"Brought to you by Peter Wagner", 0);
peter->SetAlignment(B_ALIGN_CENTER);
peter->SetViewColor(about_frame->ViewColor());
about_frame->AddChild(peter);
return view;
}
status_t CalcView::Archive(BMessage *msg, bool deep) const
{
BView::Archive(msg, deep);
// msg->AddString("class", "CalcView");
msg->AddString("add_on", "application/x-vnd.Be-calculator");
return B_OK;
}
BArchivable *CalcView::Instantiate(BMessage *msg)
{
if (validate_instantiation(msg, "CalcView"))
return new CalcView(msg);
else
return NULL;
}
CalcView::~CalcView()
{
}
static void ConnectButtonMessages(BView *target, const BView *which)
{
BView *child = which->ChildAt(0);
while (child != NULL)
{
BControl * button = (BControl *)child;
button->SetTarget(target);
child = child->NextSibling();
}
}
void CalcView::AllAttached()
{
BView::AllAttached();
lcd->SetHighColor(51,51,51);
MakeFocus();
ChangeHighlight();
}
void CalcView::AttachedToWindow()
{
BView::AttachedToWindow();
// Make buttons send their messages to this view instead of the
// [default] enclosing window.
ConnectButtonMessages(this, FindView("trig area"));
ConnectButtonMessages(this, FindView("const area"));
ConnectButtonMessages(this, FindView("keypad area"));
ConnectButtonMessages(this, FindView("func area"));
}
void CalcView::KeyDown(const char *bytes, int32 numBytes)
{
for (int i=0; i<numBytes; i++) {
char key = bytes[i];
BButton *button = NULL;
switch(key) {
case '¸':
case '¹':
case 'p':
case 'P':
button = (BButton *)FindView("pi");
break;
case 'C':
case 'c':
button = (BButton *)FindView("clr");
break;
case 'e':
case 'E':
button = (BButton *)FindView("exp");
break;
case '`':
button = (BButton *)FindView("-/+");
break;
case '(':
case ')':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '=':
case '/':
case '*':
case '-':
case '+':
case '.':
case '^':
case '!':
char name[2];
if (isalpha(key)) key = tolower(key);
name[0] = key;
name[1] = '\0';
button = (BButton *)FindView(name);
break;
case 10:
button = (BButton *)FindView("entr");
break;
case 127:
button = (BButton *)FindView(".");
break;
default:
button = button;
break;
}
if (button != NULL) {
button->SetValue(1);
snooze(100000);
button->SetValue(0);
snooze(20000);
BMessage msg(*button->Message());
SendKeystroke(msg.what);
}
}
}
static void DoubleToBinary(double *dPtr, char *str)
{
unsigned char *p = (unsigned char *)dPtr;
str[sizeof(double)*8] = '\0';
const int bits = sizeof(double) * 8;
unsigned short endian_test = 1;
if(((unsigned char *)&endian_test)[0] != 0) {
// little-endian
for (int i=0; i<bits; i++)
str[i] = (p[(sizeof(double) - i/8) - 1] & (128 >> (i&7))) ? '1' : '0';
}
else {
// Big endian
for (int i=0; i<bits; i++)
str[i] = (p[i/8] & (128 >> (i&7))) ? '1' : '0';
}
}
static char * Mid(const char *str, int start, int stop, char *str_out)
{
char *s = str_out;
for (int i=start; i<stop; i++)
*s++ = str[i];
*s = '\0';
return str_out;
}
void CalcView::SendKeystroke(ulong key)
{
calc.DoCommand(key);
BButton *trig_inverse = (BButton *)FindView("trgA");
trig_inverse->SetValue(calc.TrigInverseActive()?1:0);
BButton *trig_mode = (BButton *)FindView("trgM");
trig_mode->SetLabel(calc.TrigIsRadians()?"rad":"deg");
// Update LCD display.
char engine_str[64];
calc.GetValue(engine_str);
lcd->SetText(engine_str);
if (binary_sign_view && binary_exponent_view && binary_number_view) {
// Update binary representation of current display.
double d = calc.GetValue();
char str[300], str2[300];
DoubleToBinary(&d, str);
binary_sign_view->SetText(Mid(str, 0,1, str2));
binary_exponent_view->SetText(Mid(str, 1,12, str2));
Mid(str, 13,sizeof(double)*8, str2);
while(binary_number_view->StringWidth(str2) >= binary_number_view->Bounds().Width()
&& strlen(str2) > 24) {
str2[20] = str2[21] = str2[22] = '.';
strcpy(str2+23, str2+24);
}
binary_number_view->SetText(str2);
}
}
static bool IsSystemCommand(unsigned long what)
{
for (int zz=0; zz<4; zz++) {
char c = (char)(what >> (zz*8));
if (!isupper(c) && c!='_') return false;
}
return true;
}
void CalcView::About()
{
(new BAlert("About Calculator", "Calculator (the Replicant version)\n\n Brought to you by Peter Wagner.\n Copyright 1998.","OK"))->Go();
}
void CalcView::MessageReceived(BMessage *message)
{
switch (message->what) {
case B_ABOUT_REQUESTED:
CalcView::About();
break;
case B_COPY: {
double d;
char str[64];
d = calc.GetValue(str);
if (be_clipboard->Lock())
{
be_clipboard->Clear();
BMessage *clipper = be_clipboard->Data();
clipper->AddDouble("value", d);
clipper->AddData("text/plain", 'MIME', str, strlen(str));
be_clipboard->Commit();
be_clipboard->Unlock();
}
}
break;
case B_PASTE: {
const void *data = NULL;
ssize_t sz;
if (be_clipboard->Lock()) {
BMessage *clipper = be_clipboard->Data();
status_t status = clipper->FindData("text/plain", 'MIME', &data, &sz);
if (status == B_OK && data!=NULL)
KeyDown((const char *)data, (int32)sz);
/*
// What the heck was on the clipboard !??!
{
char *name;
uint32 type;
int32 count;
char typeS[5];
for ( int32 i = 0;
clipper->GetInfo(B_ANY_TYPE, i, &name, &type, &count) == B_OK;
i++ )
{
for (int z=0; z<4; z++)
{
typeS[z] = (char)(type >> 24);
type = type << 8;
}
cout << i << ": " << name << " " << typeS << "\n";
}
}
*/
be_clipboard->Unlock();
}
}
break;
default:
if (IsSystemCommand(message->what))
BView::MessageReceived(message);
else {
SendKeystroke(message->what);
MakeFocus();
ChangeHighlight();
}
break;
}
/*
// What the heck was that message?!!
char str[5];
str[4] = '\0';
ulong msg = message->what;
for (int i=0; i<4; i++)
{
str[i] = (char)(msg>>24);
msg = msg << 8;
if (str[i] == '\0') str[i] = '-';
}
lcd->SetText(str);
*/
}
bool CalcView::TextWidthOK(const char *str)
{
return (lcd->StringWidth(str) < lcd->Bounds().Width()) ? true : false;
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#ifndef __CALC_VIEW__
#define __CALC_VIEW__
#include <View.h>
#include <Message.h>
#include "FrameView.h"
#include "CalcEngine.h"
class _EXPORT CalcView : public BView
{
public:
static void About(void);
static float TheWidth() { return 272; }
static float TheHeight() { return 284; }
static BRect TheRect() { return TheRect(0,0); }
static BRect TheRect(const BPoint &pt) { return TheRect(pt.x,pt.y); }
static BRect TheRect(float x, float y) { return BRect(x,y,x+TheWidth(),y+TheHeight()); }
static float ExtraHeight() { return 43; }
CalcView(BRect frame);
virtual ~CalcView();
// replicant
CalcView(BMessage *msg);
virtual status_t Archive(BMessage *msg, bool deep) const;
static BArchivable* Instantiate(BMessage *msg);
virtual void AttachedToWindow();
virtual void AllAttached();
virtual void Draw(BRect updateRect);
virtual void KeyDown(const char *bytes, int32 numBytes);
virtual void MouseDown(BPoint where);
virtual void WindowActivated(bool state);
virtual void MakeFocus(bool focusState = true);
virtual void MessageReceived(BMessage *message);
void SendKeystroke(ulong key);
virtual bool TextWidthOK(const char *str);
BView *AddExtra();
private:
void Init(void);
CalcEngine calc;
bool is_replicant;
int current_highlight;
enum { state_unknown=0, state_active, state_inactive };
void ChangeHighlight();
FrameView *lcd_frame;
BStringView *lcd;
BStringView *binary_sign_view;
BStringView *binary_exponent_view;
BStringView *binary_number_view;
};
#endif

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#include "Calculator.h"
#include "CalcWindow.h"
#include "CalcView.h"
#include "Prefs.h"
typedef struct
{
int h;
int v;
} Prefs;
CalcWindow::CalcWindow(BPoint pt)
: BWindow(CalcView::TheRect(pt), "Calculator", B_TITLED_WINDOW, B_NOT_RESIZABLE)
{
BRect r = CalcView::TheRect();
SetSizeLimits(r.right, r.right, r.bottom, r.bottom+CalcView::ExtraHeight());
SetZoomLimits(r.right, r.bottom+CalcView::ExtraHeight());
calc_view = new CalcView(r);
AddChild(calc_view);
BView *extraView = calc_view->AddExtra();
AddChild(extraView);
}
bool CalcWindow::QuitRequested()
{
Prefs prefs;
prefs.h = (int)(Frame().left);
prefs.v = (int)(Frame().top);
WritePrefs("calculator.prefs", &prefs, sizeof(prefs));
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#ifndef __CALC_WINDOW__
#define __CALC_WINDOW__
#include <Window.h>
#include <Beep.h>
#include "CalcView.h"
class CalcWindow : public BWindow
{
public:
CalcWindow(BPoint pt);
virtual bool QuitRequested();
private:
CalcView *calc_view;
};
#endif

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#include <iostream.h>
#include <Alert.h>
#include <Window.h>
#include <Application.h>
#include <Beep.h>
#include <Screen.h>
#include "Calculator.h"
#include "CalcWindow.h"
#include "Prefs.h"
typedef struct
{
int h;
int v;
} Prefs;
int main(int argc, char **argv)
{
// If we have command-line arguments, calculate and
// return. Otherwise, run the graphical interface.
if(argc > 1) {
for (int i=1; i<argc; i++) {
char *str = argv[i];
CalcEngine engine;
while (*str != '\0')
engine.DoCommand(*str++);
engine.DoCommand('='); // send an extra one, just in case
printf("%.15g\n", engine.GetValue());
}
}
else {
CalculatorApp app;
app.Run();
}
return B_OK;
}
CalculatorApp::CalculatorApp(void)
: BApplication("application/x-vnd.Haiku-Calculator")
{
Prefs prefs;
if (ReadPrefs("calculator.prefs", &prefs, sizeof(prefs)) != true) {
prefs.h = 20;
prefs.v = 70;
}
BScreen screen;
BRect r = screen.Frame();
r.left += 3;
r.top += 23;
r.right -= (20-5);
r.bottom -= -3;
if(prefs.h < r.left)
prefs.h = (int)r.left;
if(prefs.h > r.right)
prefs.h = (int)r.right;
if(prefs.v < r.top)
prefs.v = (int)r.top;
if(prefs.v > r.bottom)
prefs.v = (int)r.bottom;
wind = new CalcWindow(BPoint(prefs.h, prefs.v));
wind->Show();
}
void CalculatorApp::AboutRequested()
{
CalcView::About();
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#ifndef __CALCULATOR__
#define __CALCULATOR__
#include <Application.h>
class CalculatorApp : public BApplication
{
public:
CalculatorApp();
virtual void AboutRequested();
private:
BWindow *wind;
};
#endif

View File

@ -0,0 +1,85 @@
resource(101, "BEOS:M:STD_ICON") #'MICN' array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0000FFFFFFFFFF"
$"FFFFFFFFFFFFFFFF0019190000FFFFFF"
$"FFFFFFFFFFFFFF0019868619190000FF"
$"FFFFFFFFFFFF00198686868686193F00"
$"FFFFFFFFFF00193F3F198686863F0C00"
$"FFFFFFFF00191919193F3F863F0C000C"
$"FFFFFF00193F3F193F3F193F0C000CFF"
$"FFFF0019190C0C190C0C3F0C000C0CFF"
$"FF00193F3F193F3F193F0C000C0CFFFF"
$"00123F0C0C190C0C3F0C000C0CFFFFFF"
$"0012123F3F3F3F3F0C000C0CFFFFFFFF"
$"FF000012123F190C000C0CFFFFFFFFFF"
$"FFFFFF00001212000C0CFFFFFFFFFFFF"
$"FFFFFFFFFF00000C0CFFFFFFFFFFFFFF"
};
resource(101, "BEOS:L:STD_ICON") #'ICON' array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0019190000FFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0019868619190000FFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0019868686868619190000FFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFF0019868686868686868619190000FFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFF0019868686868686868686868619190000FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFF00193F1919868686868686868686868619190000"
$"FFFFFFFFFFFFFFFFFFFFFF00191919193F191986868686868686868686193F00"
$"FFFFFFFFFFFFFFFFFFFF00193F3F191919193F191986868686868686193F0C00"
$"FFFFFFFFFFFFFFFFFF00190C19190C19191919193F191986868686193F0C0C00"
$"FFFFFFFFFFFFFFFF001919190C0C19193F3F191919193F191986193F0C0C0C00"
$"FFFFFFFFFFFFFF00193F3F191919190C19190C19191919193F193F0C0C0C0019"
$"FFFFFFFFFFFF00190C19190C191919190C0C19193F3F1919193F0C0C0C001919"
$"FFFFFFFFFF001919190C0C19193F3F191919190C19190C193F0C0C0C00191919"
$"FFFFFFFF00193F3F191919190C19190C191919190C0C193F0C0C0C0019191919"
$"FFFFFF00190C19190C191919190C0C19193F3F1919193F0C0C0C0019191919FF"
$"FFFFFF003F190C0C19193F3F191919190C19190C193F0C0C0C0019191919FFFF"
$"FFFFFF00123F3F19190C19190C191919190C0C193F0C0C0C0019191919FFFFFF"
$"FFFFFF001212123F3F190C0C19193F3F1919193F0C0C0C0019191919FFFFFFFF"
$"FFFFFF0012121212123F3F19190C19190C193F0C0C0C0019191919FFFFFFFFFF"
$"FFFFFF00001212121212123F3F190C0C193F0C0C0C0019191919FFFFFFFFFFFF"
$"FFFFFFFFFF00001212121212123F3F193F0C0C0C0019191919FFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFF00001212121212123F0C0C0C0019191919FFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF000012121212000C0C0019191919FFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFF00001212000C0019191919FFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFF0000000019191919FFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0019191919FFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
};
resource(1, "BEOS:FILE_TYPES") message;
resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku-calculator";
resource(1, "BEOS:APP_VERSION") #'APPV' array {
$"010000000000000000000000000000000000000043616C63756C61746F720000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000536369656E74696669632043"
$"616C63756C61746F722077697468205265706C6963616E7420546563686E6F6C"
$"6F67790000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000"
};
resource(1, "BEOS:APP_FLAGS") #'APPF' $"01000000";

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#include <Button.h>
#include "FrameView.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
A FrameView is a subclass of a BView that draws a simple beveled
rectangle just inside the view's bounds.
The bevel_style parameter is currently unused--the only style available
is a 1-pixel inset bevel.
The contents of the view are erased to the "view color." The left and
top edges are drawn in the view's high color and the right and bottom
edges are drawn inthe view's low color. You may set the high, low,
and view colors after creation to customize the FrameView's look.
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
BArchivable *FrameView::Instantiate(BMessage *archive)
{
if ( validate_instantiation(archive, "FrameView"))
return new FrameView(archive);
return NULL;
}
FrameView::FrameView(BRect frame, const char *name,
ulong resizeMask, int in_bevel_indent)
: BView(frame, name, resizeMask, B_WILL_DRAW|B_FRAME_EVENTS)
{
static const rgb_color c = {215, 215, 215, 0};
ColoringBasis(c);
bevel_indent = in_bevel_indent;
}
FrameView::FrameView(BMessage *data)
: BView(data)
{
static const rgb_color c = {215, 215, 215, 0};
ColoringBasis(c);
int32 i;
if(data->FindInt32("bevel_indent", &i) != B_OK)
i = 1;
if(i < 0)
i = 0;
if(i > 10)
i = 10;
bevel_indent = i;
}
void FrameView::MouseDown(BPoint where)
{
// Pass unused mouse clicks up the view hierarchy.
BView *view = Parent();
if(view != NULL)
view->MouseDown(where);
}
FrameView::FrameView(const BPoint &where, const char *name, uint32 resizeMask,
int items_wide, int items_high,
int bevel, int key_border, int key_height, int key_width,
const ClusterInfo button_info[])
: BView(BRect(where.x-bevel, where.y-bevel,
where.x+bevel+key_border+items_wide*(key_border+key_width)-1,
where.y+bevel+key_border+items_high*(key_border+key_height)-1),
name, resizeMask, B_WILL_DRAW|B_FRAME_EVENTS)
{
static const rgb_color c = {215, 215, 215, 0};
ColoringBasis(c);
bevel_indent = bevel;
for (int y=0; y<items_high; y++) {
for (int x=0; x<items_wide; x++) {
const ClusterInfo *info = &(button_info[x + y*items_wide]);
char name[5];
char *p=name;
for (int i=0; i<4; i++)
if (((info->message >> (24-8*i)) & 0x00FF) != 0)
*p++ = (char)(info->message >> (24-8*i));
*p = '\0';
if (info->message != 0) {
BRect r;
r.left = bevel_indent + key_border + x*(key_border+key_width);
r.right = r.left + key_width;
r.top = bevel_indent + key_border + y*(key_border+key_height);
r.bottom = r.top + key_height;
BMessage *msg = new BMessage(info->message);
BButton *button = new BButton(r, name, info->label, msg);
AddChild(button);
}
}
}
}
status_t FrameView::Archive(BMessage *msg, bool deep) const
{
BView::Archive(msg, deep);
msg->AddString("class", "FrameView");
msg->AddInt32("bevel_indent", (int32)bevel_indent);
return B_OK;
}
#define min(x,y) ((x<y)?x:y)
#define max(x,y) ((x>y)?x:y)
void FrameView::ColoringBasis(rgb_color basis_color)
{
rgb_color view_color = basis_color;
view_color.red = min(view_color.red+15, 255);
view_color.green = min(view_color.green+15, 255);
view_color.blue = min(view_color.blue+15, 255);
SetViewColor(view_color);
rgb_color hi_color = basis_color;
hi_color.red = max(hi_color.red-45, 0);
hi_color.green = max(hi_color.green-45, 0);
hi_color.blue = max(hi_color.blue-45, 0);
SetHighColor(hi_color);
rgb_color low_color = basis_color;
low_color.red = min(low_color.red+45, 255);
low_color.green = min(low_color.green+45, 255);
low_color.blue = min(low_color.blue+45, 255);
SetLowColor(low_color);
}
void FrameView::AttachedToWindow()
{
BView *view = Parent();
if (view != NULL)
ColoringBasis(view->ViewColor());
}
void FrameView::Draw(BRect)
{
BRect r = Bounds();
// r.InsetBy(bevel_indent/2, bevel_indent/2);
// SetPenSize(bevel_indent);
for (int i=0; i<bevel_indent; i++) {
StrokeLine(r.RightTop(), r.RightBottom(), B_SOLID_LOW);
StrokeLine(r.RightBottom(), r.LeftBottom(), B_SOLID_LOW);
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
StrokeLine(r.LeftBottom(), r.LeftTop(), B_SOLID_HIGH);
r.InsetBy(1,1);
}
}
void FrameView::FrameResized(float new_width, float new_height)
{
BRect r = Bounds();
r.InsetBy(bevel_indent,bevel_indent);
rgb_color old_color = HighColor();
SetHighColor(ViewColor());
FillRect(r);
SetHighColor(old_color);
Draw(Bounds());
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#ifndef __FRAME_VIEW__
#define __FRAME_VIEW__
#include <View.h>
class _EXPORT FrameView : public BView
{
public:
FrameView(BRect frame, const char *name,
uint32 resizeMask, int bevel_indent=1);
FrameView(BMessage *data);
virtual status_t Archive(BMessage *msg, bool deep) const;
static BArchivable * Instantiate(BMessage *archive);
virtual void Draw(BRect updateRect);
virtual void FrameResized(float new_width, float new_height);
virtual void AttachedToWindow();
void MouseDown(BPoint where);
void ColoringBasis(rgb_color view_color);
typedef struct
{
char *label;
uint32 message;
} ClusterInfo;
FrameView(const BPoint &where, const char *name,
uint32 resizeMask, int items_wide,
int items_high, int bevel, int key_border,
int key_height, int key_width,
const ClusterInfo button_info[]);
private:
int bevel_indent;
};
#endif

View File

@ -0,0 +1,14 @@
SubDir HAIKU_TOP src apps calculator ;
SetSubDirSupportedPlatformsBeOSCompatible ;
Application Calculator :
CalcEngine.cpp
Calculator.cpp
CalcView.cpp
CalcWindow.cpp
FrameView.cpp
Prefs.cpp
: be
: Calculator.rdef
;

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#include <StorageKit.h>
#include <string.h>
#include <iostream.h>
#include "Prefs.h"
bool ReadPrefs(const char *prefsname, void *prefs, size_t sz)
{
BPath path;
find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
BDirectory dir;
dir.SetTo(path.Path());
BEntry entry;
if (dir.FindEntry(prefsname, &entry) == B_OK) {
BFile file(&entry, O_RDONLY);
if (file.InitCheck() == B_OK) {
if ((size_t)file.Read(prefs, sz) == sz)
return true;
}
}
memset(prefs, 0, sz);
return false;
}
bool WritePrefs(const char *prefsname, void *prefs, size_t sz)
{
BPath path;
find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
BDirectory dir;
dir.SetTo(path.Path());
BFile file;
if (dir.CreateFile(prefsname, &file, false) == B_OK) {
if ((size_t)file.Write(prefs, sz) == sz)
return true;
}
return false;
}

View File

@ -0,0 +1,14 @@
/*
* Copyright (c) 2006, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Peter Wagner <pwagner@stanfordalumni.org>
*/
#ifndef __PREFS__
#define __PREFS__
bool ReadPrefs(const char *prefsname, void *prefs, size_t sz);
bool WritePrefs(const char *prefsname, void *prefs, size_t sz);
#endif