diff options
author | Miguel Alvarez <miguel@laptop.org> | 2007-07-13 22:08:13 (GMT) |
---|---|---|
committer | Miguel Alvarez <miguel@laptop.org> | 2007-07-13 22:08:13 (GMT) |
commit | 4fafcca69070d80c19f8774c9cb2159b9b7dc228 (patch) | |
tree | 5a0d4709ac1455727c016fbad77ecee2c4e6e3b0 | |
parent | 2d1cdb0a0003b51a00589261fab8f707816bf1ed (diff) |
Initial import
-rw-r--r-- | CalcActivity.py | 172 | ||||
-rw-r--r-- | CalcActivity.pyc | bin | 9120 -> 12765 bytes | |||
-rw-r--r-- | eqnparser.py | 44 | ||||
-rw-r--r-- | eqnparser.pyc | bin | 20088 -> 21451 bytes | |||
-rw-r--r-- | layout.py | 118 | ||||
-rw-r--r-- | layout.pyc | bin | 9159 -> 10451 bytes | |||
-rw-r--r-- | mathlib.py | 94 | ||||
-rw-r--r-- | mathlib.pyc | bin | 9122 -> 10812 bytes | |||
-rw-r--r-- | toolbars.py | 38 | ||||
-rw-r--r-- | toolbars.pyc | bin | 10441 -> 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 Binary files differindex 7bcbcca..5f50a18 100644 --- a/CalcActivity.pyc +++ b/CalcActivity.pyc 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 Binary files differindex 2d642ad..e825fb1 100644 --- a/eqnparser.pyc +++ b/eqnparser.pyc @@ -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) Binary files differ@@ -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 Binary files differindex 69ddc6f..339c50a 100644 --- a/mathlib.pyc +++ b/mathlib.pyc 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 Binary files differindex 711c541..955dcc6 100644 --- a/toolbars.pyc +++ b/toolbars.pyc 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) + |