Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel Alvarez <miguel@laptop.org>2007-07-13 22:08:13 (GMT)
committer Miguel Alvarez <miguel@laptop.org>2007-07-13 22:08:13 (GMT)
commit4fafcca69070d80c19f8774c9cb2159b9b7dc228 (patch)
tree5a0d4709ac1455727c016fbad77ecee2c4e6e3b0
parent2d1cdb0a0003b51a00589261fab8f707816bf1ed (diff)
Initial import
-rw-r--r--CalcActivity.py172
-rw-r--r--CalcActivity.pycbin9120 -> 12765 bytes
-rw-r--r--eqnparser.py44
-rw-r--r--eqnparser.pycbin20088 -> 21451 bytes
-rw-r--r--layout.py118
-rw-r--r--layout.pycbin9159 -> 10451 bytes
-rw-r--r--mathlib.py94
-rw-r--r--mathlib.pycbin9122 -> 10812 bytes
-rw-r--r--toolbars.py38
-rw-r--r--toolbars.pycbin10441 -> 11022 bytes
-rw-r--r--toolbars.py~123
11 files changed, 467 insertions, 122 deletions
diff --git a/CalcActivity.py b/CalcActivity.py
index 8a773d9..992e4f7 100644
--- a/CalcActivity.py
+++ b/CalcActivity.py
@@ -1,11 +1,13 @@
-# CalcActivity.py, sugar calculator, by Reinier Heeres <reinier@heeres.eu>
+# CalcActivity.py, sugar calculator, by:
+# Reinier Heeres <reinier@heeres.eu>
+# Miguel Alvarez <miguel@laptop.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
+# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
@@ -32,6 +34,11 @@ import gtk
import pango
from sugar.activity import activity
+import sugar.profile
+from sugar.graphics.canvasicon import CanvasIcon
+from sugar.graphics.xocolor import XoColor
+from sugar.graphics import color
+from sugar.graphics import font
from layout import CalcLayout
from mathlib import MathLib
@@ -43,19 +50,31 @@ class CalcActivity(activity.Activity):
TYPE_OP_PRE = 2
TYPE_OP_POST = 3
TYPE_TEXT = 4
-
+
+ FONT_SMALL="sans bold 14"
+ FONT_BIG = "sans bold 20"
+ FONT_BIG_NARROW = "sans italic 20"
+ FONT_BIGGER = "sans bold 24"
+
def __init__(self, handle):
activity.Activity.__init__(self, handle)
self.set_title("Calc2")
self.connect("key_press_event", self.keypress_cb)
self.connect("destroy", self.cleanup_cb)
-
+ self.color = sugar.profile.get_color()
+## self.icon = CanvasIcon(
+## icon_name='theme:stock-buddy',
+## xo_color=XoColor(self.color))
self.layout = CalcLayout(self)
self.label_entry = self.layout.label_entry
self.text_entry = self.layout.text_entry
self.history = self.layout.history
-
+ self.last_eq = self.layout.last_eq.get_buffer()
+
+ self.old_eqs = []
+ self.old_changed = False
+ self.show_vars = False
self.reset()
self.parser = EqnParser()
@@ -71,31 +90,97 @@ class CalcActivity(activity.Activity):
s = self.text_entry.get_text()
label = self.label_entry.get_text()
_logger.debug('process(): parsing \'%s\', label: \'%s\'', s, label)
-
- buf = self.history.get_buffer()
-
+ self.refresh_bar()
res = self.parser.parse(s)
+ text = ""
+ if len(label) > 0:
+ text += label + ': ' + s
+ offset = len(label)+2
+ else:
+ text += s
+ offset = 0
+
if res is not None:
- buf.insert(buf.get_start_iter(), '\t= ' + self.ml.format_number(res) + '\n')
+ text += '\n= ' + self.ml.format_number(res)
self.text_entry.set_text('')
self.parser.set_var('Ans', self.ml.format_number(res))
-
if len(label) > 0:
self.label_entry.set_text('')
self.parser.set_var(label, s)
-
else:
pos = self.parser.get_error_offset()
- self.text_entry.set_position(pos)
- buf.insert(buf.get_start_iter(), '\tError at %d\n' % pos)
-
- if len(label) > 0:
- buf.insert(buf.get_start_iter(), label + ': ' + s + '\n')
+ if pos == len(text) - 1:
+ text += '_'
+ offset += pos
+ text += '\nError at %d' % pos
+ self.last_eq.set_text(text)
+ eq_start = self.last_eq.get_start_iter()
+ eq_middle = self.last_eq.get_iter_at_line(1)
+ eq_end = self.last_eq.get_end_iter()
+ self.last_eq.apply_tag(self.last_eq.create_tag(font=self.FONT_BIG_NARROW),
+ eq_start, eq_middle)
+ self.last_eq.apply_tag(self.last_eq.create_tag(font=self.FONT_BIGGER,
+ justification=gtk.JUSTIFY_RIGHT), eq_middle, eq_end)
+ if res is None:
+ eq_start.forward_chars(offset)
+ end2 = self.last_eq.get_start_iter()
+ end2.forward_chars(offset+1)
+ self.last_eq.apply_tag(self.last_eq.create_tag(foreground='#FF0000'),
+ eq_start, end2)
+ self.last_eq.apply_tag(self.last_eq.create_tag(foreground = '#FF0000'),
+ eq_middle, eq_end)
else:
- buf.insert(buf.get_start_iter(), s + '\n')
-
+ self.old_eqs.insert(0, (label, s, res, self.color)) #TODO: add author, maybe colors
+ self.old_changed = True
return res is not None
+ def refresh_bar(self):
+ if not self.layout.varbut.selected:
+ self.refresh_history()
+ else:
+ self.refresh_vars()
+
+ def refresh_vars(self):
+ list = []
+ for name,value in self.parser.get_vars():
+ w = gtk.TextView()
+ b = w.get_buffer()
+ b.set_text(name + ":\t" + value)
+ list.append(w)
+ self.layout.show_history(list)
+
+ def refresh_history(self):
+ if not self.old_changed:
+ return
+ list = []
+ i = 0
+ for (label, eq, res, color) in self.old_eqs:
+ text = ""
+ if len(label) > 0:
+ text += str(label)+": "
+ r = self.ml.format_number(res)
+ text += str(eq)+"\n="+str(r)
+ w = gtk.TextView()
+ w.connect('button-press-event', lambda w,e,j: self.text_entry.set_text(self.old_eqs[j][1]), i+1)
+ b = w.get_buffer()
+## b.modify_bg(gtk.STATE_ACTIVE | gtk.STATE_NORMAL,
+## gtk.gdk.color_parse(self.color.get_fill_color()))
+ b.set_text(text)
+ iter_start = b.get_start_iter()
+ iter_end = b.get_end_iter()
+ iter_middle = b.get_iter_at_line(1)
+ b.apply_tag(b.create_tag(font=self.FONT_SMALL),
+ iter_start, iter_middle)
+ b.apply_tag(b.create_tag(font=self.FONT_BIG,
+ justification=gtk.JUSTIFY_RIGHT),
+ iter_middle, iter_end)
+ b.apply_tag(b.create_tag(foreground=self.color.get_fill_color()),
+ iter_start, iter_end)
+ list.append(w)
+ i += 1
+ self.layout.show_history(list)
+ self.old_changed = False
+
def clear(self):
_logger.debug('Clearing...')
self.text_entry.set_text('')
@@ -112,6 +197,8 @@ class CalcActivity(activity.Activity):
def add_text(self, c):
pos = self.text_entry.get_position()
+ if pos == 0 and c in self.parser.get_diadic_operators():
+ c = 'Ans'+c
self.text_entry.insert_text(c, pos)
self.text_entry.grab_focus()
self.text_entry.set_position(pos + len(c))
@@ -155,26 +242,28 @@ class CalcActivity(activity.Activity):
self.add_text(key)
keymap = {
- 'Return': lambda: self.process(),
- 'period': '.',
- 'equal': '=',
- 'plus': '+',
- 'minus': '-',
- 'asterisk': '*',
- 'slash': '/',
- 'BackSpace': lambda: self.remove_character(-1),
- 'Delete': lambda: self.remove_character(1),
- 'parenleft': '(',
- 'parenright': ')',
- 'exclam': '!',
- 'ampersand': '&',
- 'bar': '|',
- 'asciicircum': '^',
- 'less': '<',
- 'greater': '>',
- 'Left': lambda: self.move_left(),
- 'Right': lambda: self.move_right(),
- 'colon': lambda: self.label_entered()
+ 'Return': lambda: self.process(),
+ 'period': '.',
+ 'equal': '=',
+ 'plus': '+',
+ 'minus': '-',
+ 'asterisk': '*',
+ 'slash': '/',
+ 'BackSpace': lambda: self.remove_character(-1),
+ 'Delete': lambda: self.remove_character(1),
+ 'parenleft': '(',
+ 'parenright': ')',
+ 'exclam': '!',
+ 'ampersand': '&',
+ 'bar': '|',
+ 'asciicircum': '^',
+ 'less': '<',
+ 'greater': '>',
+ 'Left': lambda: self.move_left(),
+ 'Right': lambda: self.move_right(),
+ 'colon': lambda: self.label_entered(),
+ 'Home': lambda: self.text_entry.set_position(0),
+ 'End': lambda: self.text_entry.set_position(len(self.text_entry.get_text()))
}
if keymap.has_key(key):
f = keymap[key]
@@ -202,14 +291,13 @@ class CalcActivity(activity.Activity):
self.text_entry.set_position(pos + len(str) + 1)
else:
self.text_entry.set_text(text[:start] + str + '(' + text[start:end] + ')' + text[end:])
- if pos > end:
- self.text_entry.set_position(pos + len(str) + 2)
- elif pos > start:
- self.text_entry.set_position(pos + len(str) + 1)
+ self.text_entry.set_position(pos + len(str) + 2)
elif type == self.TYPE_OP_PRE:
if len(sel) is 2:
pos = start
+ elif pos == 0:
+ str = 'Ans'+str
self.text_entry.insert_text(str, pos)
self.text_entry.set_position(pos + len(str))
diff --git a/CalcActivity.pyc b/CalcActivity.pyc
index 7bcbcca..5f50a18 100644
--- a/CalcActivity.pyc
+++ b/CalcActivity.pyc
Binary files differ
diff --git a/eqnparser.py b/eqnparser.py
index c2b9719..807ef51 100644
--- a/eqnparser.py
+++ b/eqnparser.py
@@ -1,4 +1,21 @@
-#eqnparser.py
+# eqnparser.py, generic equation parser by Reinier Heeres <reinier@heeres.eu>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Change log:
+# 2007-07-03: rwh, first version
import logging
_logger = logging.getLogger('EqnParser')
@@ -117,6 +134,10 @@ class EqnParser:
self.register_function('acosh', 1, lambda x: self.ml.acosh(x[0]))
self.register_function('atanh', 1, lambda x: self.ml.atanh(x[0]))
+ self.register_function('round', 1, lambda x: self.ml.round(x[0]))
+ self.register_function('floor', 1, lambda x: self.ml.floor(x[0]))
+ self.register_function('ceil', 1, lambda x: self.ml.ceil(x[0]))
+
self.register_operator('+', self.OP_DIADIC, 0, lambda x: self.ml.add(x[0], x[1]))
self.register_operator('+', self.OP_PRE, 1, lambda x: x[0])
self.register_operator('-', self.OP_DIADIC, 0, lambda x: self.ml.sub(x[0], x[1]))
@@ -150,7 +171,14 @@ class EqnParser:
for c in op:
if c not in self.OP_CHARS:
self.OP_CHARS += c
-
+
+ def get_diadic_operators(self):
+ res = []
+ for (op, type, presedence, f) in self.operators:
+ if type == self.OP_DIADIC:
+ res.append(op)
+ return res
+
def reset_variable_level(self, level):
return
# for i in self.variables.keys():
@@ -174,7 +202,11 @@ class EqnParser:
_logger.debug('variable %s not defined', name)
ps.set_type(self.TYPE_SYMBOLIC)
return None
-
+ def get_vars(self):
+ list = []
+ for name in self.variables:
+ list.append((name, self.variables[name]))
+ return list
def eval_func(self, func, args, level):
if func not in self.functions:
_logger.error('Function \'%s\' not defined', func)
@@ -387,7 +419,11 @@ class EqnParser:
else:
left_val = self.parse_var_func(ps)
- if op is None and left_val is not None:
+ if not ps.more() and ps.level > 0:
+ _logger.debug('Parse error: \')\' expected')
+ ps.set_error_code(ParserState.PARSE_ERROR)
+ return None
+ elif op is None and left_val is not None:
_logger.debug('returning %s', self.ml.format_number(left_val))
return left_val
else:
diff --git a/eqnparser.pyc b/eqnparser.pyc
index 2d642ad..e825fb1 100644
--- a/eqnparser.pyc
+++ b/eqnparser.pyc
Binary files differ
diff --git a/layout.py b/layout.py
index b32266d..2a0239a 100644
--- a/layout.py
+++ b/layout.py
@@ -3,8 +3,8 @@ import pygtk
pygtk.require('2.0')
import gtk
import pango
-
from sugar.activity import activity
+from sugar.graphics import font
from toolbars import *
@@ -20,32 +20,32 @@ class CalcLayout:
def create_button_data(self):
self.button_data = [
# [x, y, width, label, bgcol, cb]
- [1, 1, 1, '7', self.col_gray2, lambda w: self._parent.add_text('7')],
- [2, 1, 1, '8', self.col_gray2, lambda w: self._parent.add_text('8')],
- [3, 1, 1, '9', self.col_gray2, lambda w: self._parent.add_text('9')],
+ [0, 0, 1, '7', self.col_gray2, lambda w: self._parent.add_text('7')],
+ [1, 0, 1, '8', self.col_gray2, lambda w: self._parent.add_text('8')],
+ [2, 0, 1, '9', self.col_gray2, lambda w: self._parent.add_text('9')],
- [1, 2, 1, '4', self.col_gray2, lambda w: self._parent.add_text('4')],
- [2, 2, 1, '5', self.col_gray2, lambda w: self._parent.add_text('5')],
- [3, 2, 1, '6', self.col_gray2, lambda w: self._parent.add_text('6')],
+ [0, 1, 1, '4', self.col_gray2, lambda w: self._parent.add_text('4')],
+ [1, 1, 1, '5', self.col_gray2, lambda w: self._parent.add_text('5')],
+ [2, 1, 1, '6', self.col_gray2, lambda w: self._parent.add_text('6')],
- [1, 3, 1, '1', self.col_gray2, lambda w: self._parent.add_text('1')],
- [2, 3, 1, '2', self.col_gray2, lambda w: self._parent.add_text('2')],
- [3, 3, 1, '3', self.col_gray2, lambda w: self._parent.add_text('3')],
+ [0, 2, 1, '1', self.col_gray2, lambda w: self._parent.add_text('1')],
+ [1, 2, 1, '2', self.col_gray2, lambda w: self._parent.add_text('2')],
+ [2, 2, 1, '3', self.col_gray2, lambda w: self._parent.add_text('3')],
- [1, 4, 1, '0', self.col_gray2, lambda w: self._parent.add_text('0')],
- [2, 4, 1, '.', self.col_gray2, lambda w: self._parent.add_text('.')],
- [3, 4, 1, 'Ans', self.col_gray2, lambda w: self._parent.add_text('Ans')],
+ [0, 3, 1, '0', self.col_gray2, lambda w: self._parent.add_text('0')],
+ [1, 3, 1, '.', self.col_gray2, lambda w: self._parent.add_text('.')],
+ [2, 3, 1, 'Ans', self.col_gray2, lambda w: self._parent.add_text('Ans')],
- [4, 1, 3, 'clear', self.col_gray1, lambda w: self._parent.clear()],
+ [3, 0, 3, 'clear', self.col_gray1, lambda w: self._parent.clear()],
- [4, 2, 1, '+', self.col_gray3, lambda w: self._parent.add_character('+')],
- [5, 2, 1, '-', self.col_gray3, lambda w: self._parent.add_character('-')],
- [6, 2, 1, '(', self.col_gray3, lambda w: self._parent.add_character('(')],
- [4, 3, 1, 'x', self.col_gray3, lambda w: self._parent.add_character('*')],
- [5, 3, 1, '/', self.col_gray3, lambda w: self._parent.add_character('/')],
- [6, 3, 1, ')', self.col_gray3, lambda w: self._parent.add_character(')')],
-
- [4, 4, 3, 'enter', self.col_gray1, lambda w: self._parent.process()],
+ [3, 1, 1, '+', self.col_gray3, lambda w: self._parent.add_text('+')],
+ [4, 1, 1, '-', self.col_gray3, lambda w: self._parent.add_text('-')],
+ [5, 1, 1, '(', self.col_gray3, lambda w: self._parent.add_text('(')],
+ [3, 2, 1, 'x', self.col_gray3, lambda w: self._parent.add_text('*')],
+ [4, 2, 1, '/', self.col_gray3, lambda w: self._parent.add_text('/')],
+ [5, 2, 1, ')', self.col_gray3, lambda w: self._parent.add_text(')')],
+
+ [3, 3, 3, 'enter', self.col_gray1, lambda w: self._parent.process()],
]
def create_dialog(self):
@@ -67,61 +67,83 @@ class CalcLayout:
self.col_gray2 = self.create_color(0.51, 0.51, 0.53)
self.col_gray3 = self.create_color(0.30, 0.30, 0.31)
self.col_black = self.create_color(0.00, 0.00, 0.00)
+ self.col_red = self.create_color(1.00, 0.00, 0.00)
-# Container
- hc1 = gtk.HBox(False, 10)
- hc1.set_border_width(10)
+# Big - Table
+ self.grid = gtk.Table(16, 10, True)
+ self.grid.set_row_spacings(6)
+ self.grid.set_col_spacings(6)
if issubclass(type(self._parent), gtk.Bin) and self._parent.get_child() is not None:
- self._parent.get_child().add(hc1)
+ self._parent.get_child().add(self.grid)
else:
- self._parent.add(hc1)
+ self._parent.add(self.grid)
# Left part: container and input
- vc1 = gtk.VBox(False, 10)
- hc1.add(vc1)
- hc2 = gtk.HBox(False, 10)
- vc1.add(hc2)
+ hc1 = gtk.HBox(False, 10)
label1 = gtk.Label(_('Label:'))
- hc2.add(label1)
+ hc1.add(label1)
self.label_entry = gtk.Entry()
- hc2.add(self.label_entry)
+ hc1.add(self.label_entry)
+ self.grid.attach(hc1, 0, 6, 0, 1)
+
self.text_entry = gtk.Entry()
- vc1.add(self.text_entry)
self.text_entry.set_size_request(400, 100)
self.text_entry.connect('key_press_event', self._parent.ignore_key_cb)
self.text_entry.modify_font(self.font)
+ self.grid.attach(self.text_entry, 0, 6, 1, 5)
# Left part: buttons
self.pad = gtk.Table(4, 6, True)
- vc1.add(self.pad)
self.pad.set_row_spacings(6)
self.pad.set_col_spacings(6)
self.create_button_data()
self.buttons = []
- for i in range(len(self.button_data)):
- x, y, w, cap, bgcol, cb = self.button_data[i]
+ for x, y, w, cap, bgcol, cb in self.button_data:
button = self.create_button(_(cap), cb, self.col_white, bgcol, w)
self.buttons.append(button)
self.pad.attach(button, x, x+w, y, y+1)
+
+ self.grid.attach(self.pad, 0, 6, 5, 16)
# Right part: container and equation button
- vc2 = gtk.VBox(10)
- hc1.add(vc2)
- eqbut = gtk.Button('All equations')
- vc2.add(eqbut)
-
+ hc2 = gtk.HBox()
+ self.minebut = TextToggleToolButton(['All users', 'Only mine'],
+ lambda b: TextToggleToolButton.toggle_button(b))
+ self.varbut = TextToggleToolButton(['Show history ', 'Show variables'],
+ lambda b: TextToggleToolButton.toggle_button(b))
+ hc2.add(self.minebut)
+ hc2.add(self.varbut)
+ self.grid.attach(hc2, 6, 10, 0, 1)
+
# Right part: last equation
+ self.last_eq= gtk.TextView()
+ self.last_eq.set_editable(False)
+ self.last_eq.set_wrap_mode(gtk.WRAP_CHAR)
+ self.grid.attach(self.last_eq, 6, 10, 1, 5)
# Right part: history
- self.history = gtk.TextView()
- vc2.add(self.history)
- self.history.set_size_request(300, 400)
- self.history.set_editable(False)
- self.history.set_cursor_visible(False)
-
+
+## self.history = gtk.TextView()
+## self.history.set_size_request(300, 400)
+## self.history.set_editable(False)
+## self.history.set_cursor_visible(False)
+ scrolled_window = gtk.ScrolledWindow()
+ scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ self.history = gtk.VBox()
+ self.history.set_homogeneous(False)
+ scrolled_window.add_with_viewport(self.history)
+ self.grid.attach(scrolled_window, 6, 10, 5, 16)
self._parent.show_all()
+ def show_history(self, window_list):
+ if self.history is None:
+ return
+ for el in self.history.get_children():
+ self.history.remove(el)
+ for w in window_list:
+ self.history.pack_start(w,expand=False,fill=False,padding=1)
+ self._parent.show_all()
def create_button(self, cap, cb, fgcol, bgcol, width):
button = gtk.Button(cap)
self.modify_button_appearance(button, fgcol, bgcol, width)
diff --git a/layout.pyc b/layout.pyc
index 28fc3c2..8504f3d 100644
--- a/layout.pyc
+++ b/layout.pyc
Binary files differ
diff --git a/mathlib.py b/mathlib.py
index 7464552..c2e1ade 100644
--- a/mathlib.py
+++ b/mathlib.py
@@ -1,12 +1,38 @@
-#MathLib.py
+# MathLib.py, generic math library wrapper by Reinier Heeres <reinier@heeres.eu>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Change log:
+# 2007-07-03: rwh, first version
import types
import math
from decimal import Decimal
+import logging
+_logger = logging.getLogger('calc-activity')
+
+
class MathLib:
+ ANGLE_DEG = math.pi/180
+ ANGLE_RAD = 1
+ ANGLE_GRAD = 1
+
def __init__(self):
self.constants = {}
+ self.set_angle_type(self.ANGLE_DEG)
self.set_constant('true', True)
self.set_constant('false', False)
self.set_constant('pi', self.parse_number('3.14'))
@@ -21,6 +47,10 @@ class MathLib:
self.set_constant('c_n', self.parse_number('0')) #neutron properties
self.set_constant('m_n', self.parse_number('0'))
+ def set_angle_type(self, type):
+ self.angle_scaling = self.d(type)
+ _logger.debug('Angle type set to:%s',self.angle_scaling)
+
def set_constant(self, name, val):
self.constants[name] = val
@@ -31,8 +61,9 @@ class MathLib:
return None
def d(self, val):
- s = '%e' % val
- return Decimal(s)
+ s = '%.10e' % val
+ d = Decimal(s)
+ return d.normalize()
def parse_number(self, s):
return Decimal(s)
@@ -43,16 +74,31 @@ class MathLib:
return 'True'
else:
return 'False'
-
+ elif type(n) is types.NoneType:
+ return 'Error'
+ elif not isinstance(n, Decimal):
+ return 'Error (no Decimal object)'
(sign, digits, exp) = n.as_tuple()
- if sign == '-':
+ if len(digits) > 9:
+ exp += len(digits) - 9
+ digits = digits[:9]
+
+ if sign:
res = "-"
else:
res = ""
int_len = len(digits) + exp
- disp_exp = math.floor(int_len / 3) * 3
- if disp_exp == 3:
+
+ if int_len == 0:
+ if exp < -5:
+ disp_exp = exp +len(digits)
+ else:
+ disp_exp = 0
+ elif 0 < int_len < 6:
disp_exp = 0
+ else:
+ disp_exp = int_len - 1
+
dot_pos = int_len - disp_exp
for i in xrange(len(digits)):
if i == dot_pos:
@@ -61,9 +107,15 @@ class MathLib:
else:
res += '.'
res += str(digits[i])
+
+ if len(digits) < dot_pos:
+ for i in xrange(len(digits), dot_pos):
+ res += '0'
+
if disp_exp != 0:
res = res + 'e%d' % disp_exp
+ print 'fn: %r into %r' % (n, res)
return res
def is_int(self, n):
@@ -98,7 +150,10 @@ class MathLib:
return x * y
def div(self, x, y):
- return x / y
+ if y == 0:
+ return None
+ else:
+ return x / y
def pow(self, x, y):
if self.is_int(y):
@@ -141,22 +196,23 @@ class MathLib:
return res
def sin(self, x):
- return self.d(math.sin(x))
+ return self.d(math.sin(x * self.angle_scaling))
def cos(self, x):
- return self.d(math.cos(x))
+ _logger.debug('cos: x=%s, angle_scaling=%s', x, self.angle_scaling)
+ return self.d(math.cos(x * self.angle_scaling))
def tan(self, x):
- return self.d(math.tan(x))
+ return self.d(math.tan(x * self.angle_scaling))
def asin(self, x):
- return self.d(math.asin(x))
+ return self.d(math.asin(x)) / self.angle_scaling
def acos(self, x):
- return self.d(math.acos(x))
+ return self.d(math.acos(x)) / self.angle_scaling
def atan(self, x):
- return self.d(math.atan(x))
+ return self.d(math.atan(x)) / self.angle_scaling
def sinh(self, x):
return self.d(math.sinh(x))
@@ -175,3 +231,13 @@ class MathLib:
def atanh(self, x):
return self.d(math.atanh(x))
+
+ def round(self, x):
+ return self.d(round(x))
+
+ def floor(self, x):
+ return self.d(math.floor(x))
+
+ def ceil(self, x):
+ return self.d(math.ceil(x))
+
diff --git a/mathlib.pyc b/mathlib.pyc
index 69ddc6f..339c50a 100644
--- a/mathlib.pyc
+++ b/mathlib.pyc
Binary files differ
diff --git a/toolbars.py b/toolbars.py
index cb21f8b..f0cc340 100644
--- a/toolbars.py
+++ b/toolbars.py
@@ -1,7 +1,9 @@
+# toolbars.py, see CalcActivity.py for info
+
import pygtk
pygtk.require('2.0')
import gtk
-
+from mathlib import MathLib
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.toggletoolbutton import ToggleToolButton
@@ -20,12 +22,19 @@ class IconToolButton(ToolButton):
self.connect('clicked', cb)
class TextToggleToolButton(gtk.ToggleToolButton):
- def __init__(self, text, cb):
+ def __init__(self, items, cb):
gtk.ToggleToolButton.__init__(self)
- self.set_label(text)
- self.selected = False
+ self.items = items
+ self.set_label(items[0])
+ self.selected = 0
self.connect('clicked', cb)
+ @staticmethod
+ def toggle_button(button):
+ _logger.debug("Toggle button with button:%s", button)
+ button.selected = (button.selected + 1) % len(button.items)
+ button.set_label(button.items[button.selected])
+
class IconToggleToolButton(ToggleToolButton):
def __init__(self, text, cb):
ToggleToolButton.__init__(self, text)
@@ -53,7 +62,7 @@ class AlgebraToolbar(gtk.Toolbar):
self.insert(LineSeparator(), -1)
self.insert(TextToolButton('exp',
- lambda x: calc.button_pressed(calc.TYPE_OP_POST, 'exp')), -1)
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'exp')), -1)
self.insert(TextToolButton('ln',
lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'ln')), -1)
@@ -121,14 +130,15 @@ class ConstantsToolbar(gtk.Toolbar):
class FormatToolbar(gtk.Toolbar):
def __init__(self, calc):
gtk.Toolbar.__init__(self)
- self.insert(TextToggleToolButton('rad/deg',
- lambda b: FormatToolbar.toggle_button(b)), -1)
+ el = ['deg', 'rad']
+ self.insert(TextToggleToolButton(el, lambda b: FormatToolbar.update_angle_type(b,calc)),
+ -1)
@staticmethod
- def toggle_button(button):
- _logger.debug("Toggle button with button:%s",button)
- button.selected = not button.selected
- if button.selected:
- button.set_label('rad/DEG')
- else:
- button.set_label('RAD/deg')
+ def update_angle_type(b, calc):
+ TextToggleToolButton.toggle_button(b)
+ if b.items[b.selected] == 'deg':
+ calc.ml.set_angle_type(MathLib.ANGLE_DEG)
+ elif b.items[b.selected] == 'rad':
+ calc.ml.set_angle_type(MathLib.ANGLE_RAD)
+ _logger.debug('Angle type: %s', calc.ml.angle_scaling)
diff --git a/toolbars.pyc b/toolbars.pyc
index 711c541..955dcc6 100644
--- a/toolbars.pyc
+++ b/toolbars.pyc
Binary files differ
diff --git a/toolbars.py~ b/toolbars.py~
new file mode 100644
index 0000000..bb70af2
--- /dev/null
+++ b/toolbars.py~
@@ -0,0 +1,123 @@
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.toggletoolbutton import ToggleToolButton
+
+class TextToolButton(gtk.ToolButton):
+ def __init__(self, text, cb):
+ gtk.ToolButton.__init__(self)
+ self.set_label(text)
+ self.connect('clicked', cb)
+
+class IconToolButton(ToolButton):
+ def __init__(self, text, cb):
+ ToolButton.__init__(self, text)
+ self.connect('clicked', cb)
+
+class TextToggleToolButton(gtk.ToggleToolButton):
+ def __init__(self, text, cb):
+ gtk.ToggleToolButton.__init__(self)
+ self.set_label(text)
+ self.connect('clicked', cb)
+
+class IconToggleToolButton(ToggleToolButton):
+ def __init__(self, text, cb):
+ ToggleToolButton.__init__(self, text)
+ self.connect('clicked', cb)
+
+class LineSeparator(gtk.SeparatorToolItem):
+ def __init__(self):
+ gtk.SeparatorToolItem.__init__(self)
+ self.set_draw(True)
+
+class EditToolbar(gtk.Toolbar):
+ def __init__(self, calc):
+ gtk.Toolbar.__init__(self)
+
+class AlgebraToolbar(gtk.Toolbar):
+ def __init__(self, calc):
+ gtk.Toolbar.__init__(self)
+
+ self.insert(TextToolButton('square',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, '^2')), -1)
+
+ self.insert(TextToolButton('sqrt',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'sqrt')), -1)
+
+ self.insert(LineSeparator(), -1)
+
+ self.insert(TextToolButton('exp',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, 'exp')), -1)
+
+ self.insert(TextToolButton('ln',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'ln')), -1)
+
+ self.insert(LineSeparator(), -1)
+
+ self.insert(TextToolButton('fac',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, '!')), -1)
+
+class TrigonometryToolbar(gtk.Toolbar):
+ def __init__(self, calc):
+ gtk.Toolbar.__init__(self)
+
+ self.insert(TextToolButton('sin',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'sin')), -1)
+
+ self.insert(TextToolButton('cos',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'cos')), -1)
+
+ self.insert(TextToolButton('tan',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'tan')), -1)
+
+ self.insert(LineSeparator(), -1)
+
+ self.insert(TextToolButton('sinh',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'sinh')), -1)
+
+ self.insert(TextToolButton('cosh',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'cosh')), -1)
+
+ self.insert(TextToolButton('tanh',
+ lambda x: calc.button_pressed(calc.TYPE_FUNCTION, 'tanh')), -1)
+
+class BooleanToolbar(gtk.Toolbar):
+ def __init__(self, calc):
+ gtk.Toolbar.__init__(self)
+
+ self.insert(TextToolButton('and',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, '&')), -1)
+
+ self.insert(TextToolButton('or',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, '|')), -1)
+
+ self.insert(TextToolButton('xor',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, '^')), -1)
+
+ self.insert(LineSeparator(), -1)
+
+ self.insert(TextToolButton('eq',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, '=')), -1)
+
+ self.insert(TextToolButton('neq',
+ lambda x: calc.button_pressed(calc.TYPE_OP_POST, '!=')), -1)
+
+class ConstantsToolbar(gtk.Toolbar):
+ def __init__(self, calc):
+ gtk.Toolbar.__init__(self)
+
+ self.insert(TextToolButton('pi',
+ lambda x: calc.button_pressed(calc.TYPE_TEXT, 'pi')), -1)
+
+ self.insert(TextToolButton('e',
+ lambda x: calc.button_pressed(calc.TYPE_TEXT, 'e')), -1)
+
+class FormatToolbar(gtk.Toolbar):
+ def __init__(self, calc):
+ gtk.Toolbar.__init__(self)
+
+ self.insert(TextToggleToolButton('rad/deg',
+ lambda x: True), -1)
+